quiet ?= $($(shell echo $1 | sed -e s'/ .*//'))
%.o: %.cc $(global_deps)
- @mkdir -p .deps/$(@D)
+ @mkdir -p $(patsubst %/.,%,.deps/$(@D))
$(call quiet,CXX $(CPPFLAGS) $(CXXFLAGS)) -c $(FINAL_CXXFLAGS) $< -o $@ -MD -MP -MF .deps/$*.d
%.o: %.c $(global_deps)
- @mkdir -p .deps/$(@D)
+ @mkdir -p $(patsubst %/.,%,.deps/$(@D))
$(call quiet,CC $(CPPFLAGS) $(CFLAGS)) -c $(FINAL_CFLAGS) $< -o $@ -MD -MP -MF .deps/$*.d
.PHONY : clean
DEPS := $(SRCS:%.c=.deps/%.d)
DEPS := $(DEPS:%.cc=.deps/%.d)
-include $(DEPS)
+
+.SUFFIXES: # Delete the default suffixes. Old-Fashioned Suffix Rules not used.
+Notmuch 0.18 (UNRELEASED)
+=========================
+
+Command-Line Interface
+----------------------
+
+`notmuch dump` now defaults to `batch-tag` format.
+
+ The old format is still available with `--format=sup`.
+
Notmuch 0.17 (2013-12-30)
=========================
--- /dev/null
+#include <dirent.h>
+
+int main()
+{
+ struct dirent ent;
+
+ (void) ent.d_type;
+
+ return 0;
+}
case "${cur}" in
-*)
- local options="--no-hooks"
+ local options="--no-hooks --quiet"
COMPREPLY=( $(compgen -W "${options}" -- ${cur}) )
;;
esac
have_valgrind=0
fi
+printf "Checking for bash-completion (>= 1.90)... "
+if pkg-config --atleast-version=1.90 bash-completion; then
+ printf "Yes.\n"
+else
+ printf "No (will not install bash completion).\n"
+ WITH_BASH=0
+fi
+
if [ -z "${EMACSLISPDIR}" ]; then
if pkg-config --exists emacs; then
EMACSLISPDIR=$(pkg-config emacs --variable sitepkglispdir)
fi
rm -f compat/have_timegm
+printf "Checking for dirent.d_type... "
+if ${CC} -o compat/have_d_type "$srcdir"/compat/have_d_type.c > /dev/null 2>&1
+then
+ printf "Yes.\n"
+ have_d_type="1"
+else
+ printf "No (will use stat instead).\n"
+ have_d_type="0"
+fi
+rm -f compat/have_d_type
+
printf "Checking for standard version of getpwuid_r... "
if ${CC} -o compat/check_getpwuid "$srcdir"/compat/check_getpwuid.c > /dev/null 2>&1
then
# build its own version)
HAVE_STRSEP = ${have_strsep}
+# Whether struct dirent has d_type (if not, then notmuch will use stat)
+HAVE_D_TYPE = ${have_d_type}
+
# Whether the Xapian version in use supports compaction
HAVE_XAPIAN_COMPACT = ${have_xapian_compact}
\$(VALGRIND_CFLAGS) \\
-DHAVE_STRCASESTR=\$(HAVE_STRCASESTR) \\
-DHAVE_STRSEP=\$(HAVE_STRSEP) \\
+ -DHAVE_D_TYPE=\$(HAVE_D_TYPE) \\
-DSTD_GETPWUID=\$(STD_GETPWUID) \\
-DSTD_ASCTIME=\$(STD_ASCTIME) \\
-DHAVE_XAPIAN_COMPACT=\$(HAVE_XAPIAN_COMPACT) \\
\$(VALGRIND_CFLAGS) \$(XAPIAN_CXXFLAGS) \\
-DHAVE_STRCASESTR=\$(HAVE_STRCASESTR) \\
-DHAVE_STRSEP=\$(HAVE_STRSEP) \\
+ -DHAVE_D_TYPE=\$(HAVE_D_TYPE) \\
-DSTD_GETPWUID=\$(STD_GETPWUID) \\
-DSTD_ASCTIME=\$(STD_ASCTIME) \\
-DHAVE_XAPIAN_COMPACT=\$(HAVE_XAPIAN_COMPACT) \\
--- /dev/null
+# Doxyfile 1.8.4
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+DOXYFILE_ENCODING = UTF-8
+PROJECT_NAME = "Notmuch 0.17"
+PROJECT_NUMBER =
+PROJECT_BRIEF =
+PROJECT_LOGO =
+OUTPUT_DIRECTORY =
+CREATE_SUBDIRS = NO
+OUTPUT_LANGUAGE = English
+BRIEF_MEMBER_DESC = YES
+REPEAT_BRIEF = YES
+ABBREVIATE_BRIEF =
+ALWAYS_DETAILED_SEC = NO
+INLINE_INHERITED_MEMB = NO
+FULL_PATH_NAMES = NO
+STRIP_FROM_PATH =
+STRIP_FROM_INC_PATH =
+SHORT_NAMES = NO
+JAVADOC_AUTOBRIEF = YES
+QT_AUTOBRIEF = NO
+MULTILINE_CPP_IS_BRIEF = NO
+INHERIT_DOCS = YES
+SEPARATE_MEMBER_PAGES = NO
+TAB_SIZE = 8
+ALIASES =
+TCL_SUBST =
+OPTIMIZE_OUTPUT_FOR_C = YES
+OPTIMIZE_OUTPUT_JAVA = NO
+OPTIMIZE_FOR_FORTRAN = NO
+OPTIMIZE_OUTPUT_VHDL = NO
+EXTENSION_MAPPING =
+MARKDOWN_SUPPORT = YES
+AUTOLINK_SUPPORT = YES
+BUILTIN_STL_SUPPORT = NO
+CPP_CLI_SUPPORT = NO
+SIP_SUPPORT = NO
+IDL_PROPERTY_SUPPORT = YES
+DISTRIBUTE_GROUP_DOC = NO
+SUBGROUPING = YES
+INLINE_GROUPED_CLASSES = NO
+INLINE_SIMPLE_STRUCTS = NO
+TYPEDEF_HIDES_STRUCT = YES
+LOOKUP_CACHE_SIZE = 0
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+EXTRACT_ALL = NO
+EXTRACT_PRIVATE = NO
+EXTRACT_PACKAGE = NO
+EXTRACT_STATIC = NO
+EXTRACT_LOCAL_CLASSES = YES
+EXTRACT_LOCAL_METHODS = NO
+EXTRACT_ANON_NSPACES = NO
+HIDE_UNDOC_MEMBERS = NO
+HIDE_UNDOC_CLASSES = NO
+HIDE_FRIEND_COMPOUNDS = NO
+HIDE_IN_BODY_DOCS = NO
+INTERNAL_DOCS = NO
+CASE_SENSE_NAMES = YES
+HIDE_SCOPE_NAMES = NO
+SHOW_INCLUDE_FILES = NO
+FORCE_LOCAL_INCLUDES = NO
+INLINE_INFO = YES
+SORT_MEMBER_DOCS = NO
+SORT_BRIEF_DOCS = NO
+SORT_MEMBERS_CTORS_1ST = NO
+SORT_GROUP_NAMES = NO
+SORT_BY_SCOPE_NAME = NO
+STRICT_PROTO_MATCHING = NO
+GENERATE_TODOLIST = NO
+GENERATE_TESTLIST = NO
+GENERATE_BUGLIST = NO
+GENERATE_DEPRECATEDLIST= NO
+ENABLED_SECTIONS =
+MAX_INITIALIZER_LINES = 30
+SHOW_USED_FILES = NO
+SHOW_FILES = NO
+SHOW_NAMESPACES = NO
+FILE_VERSION_FILTER =
+LAYOUT_FILE =
+CITE_BIB_FILES =
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+QUIET = YES
+WARNINGS = YES
+WARN_IF_UNDOCUMENTED = YES
+WARN_IF_DOC_ERROR = YES
+WARN_NO_PARAMDOC = NO
+WARN_FORMAT = "$file:$line: $text"
+WARN_LOGFILE =
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+INPUT = lib/notmuch.h
+INPUT_ENCODING = UTF-8
+FILE_PATTERNS =
+RECURSIVE = NO
+EXCLUDE =
+EXCLUDE_SYMLINKS = NO
+EXCLUDE_PATTERNS =
+EXCLUDE_SYMBOLS =
+EXAMPLE_PATH =
+EXAMPLE_PATTERNS =
+EXAMPLE_RECURSIVE = NO
+IMAGE_PATH =
+INPUT_FILTER =
+FILTER_PATTERNS =
+FILTER_SOURCE_FILES = NO
+FILTER_SOURCE_PATTERNS =
+USE_MDFILE_AS_MAINPAGE =
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+SOURCE_BROWSER = NO
+INLINE_SOURCES = NO
+STRIP_CODE_COMMENTS = YES
+REFERENCED_BY_RELATION = NO
+REFERENCES_RELATION = NO
+REFERENCES_LINK_SOURCE = YES
+USE_HTAGS = NO
+VERBATIM_HEADERS = NO
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX = NO
+COLS_IN_ALPHA_INDEX = 5
+IGNORE_PREFIX =
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+GENERATE_HTML = NO
+HTML_OUTPUT = html
+HTML_FILE_EXTENSION = .html
+HTML_HEADER =
+HTML_FOOTER =
+HTML_STYLESHEET =
+HTML_EXTRA_STYLESHEET =
+HTML_EXTRA_FILES =
+HTML_COLORSTYLE_HUE = 220
+HTML_COLORSTYLE_SAT = 100
+HTML_COLORSTYLE_GAMMA = 80
+HTML_TIMESTAMP = YES
+HTML_DYNAMIC_SECTIONS = NO
+HTML_INDEX_NUM_ENTRIES = 100
+GENERATE_DOCSET = NO
+DOCSET_FEEDNAME = "Doxygen generated docs"
+DOCSET_BUNDLE_ID = org.doxygen.Project
+DOCSET_PUBLISHER_ID = org.doxygen.Publisher
+DOCSET_PUBLISHER_NAME = Publisher
+GENERATE_HTMLHELP = NO
+CHM_FILE =
+HHC_LOCATION =
+GENERATE_CHI = NO
+CHM_INDEX_ENCODING =
+BINARY_TOC = NO
+TOC_EXPAND = NO
+GENERATE_QHP = NO
+QCH_FILE =
+QHP_NAMESPACE = org.doxygen.Project
+QHP_VIRTUAL_FOLDER = doc
+QHP_CUST_FILTER_NAME =
+QHP_CUST_FILTER_ATTRS =
+QHP_SECT_FILTER_ATTRS =
+QHG_LOCATION =
+GENERATE_ECLIPSEHELP = NO
+ECLIPSE_DOC_ID = org.doxygen.Project
+DISABLE_INDEX = NO
+GENERATE_TREEVIEW = NO
+ENUM_VALUES_PER_LINE = 4
+TREEVIEW_WIDTH = 250
+EXT_LINKS_IN_WINDOW = NO
+FORMULA_FONTSIZE = 10
+FORMULA_TRANSPARENT = YES
+USE_MATHJAX = NO
+MATHJAX_FORMAT = HTML-CSS
+MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
+MATHJAX_EXTENSIONS =
+MATHJAX_CODEFILE =
+SEARCHENGINE = YES
+SERVER_BASED_SEARCH = NO
+EXTERNAL_SEARCH = NO
+SEARCHENGINE_URL =
+SEARCHDATA_FILE = searchdata.xml
+EXTERNAL_SEARCH_ID =
+EXTRA_SEARCH_MAPPINGS =
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+GENERATE_LATEX = NO
+LATEX_OUTPUT = latex
+LATEX_CMD_NAME = latex
+MAKEINDEX_CMD_NAME = makeindex
+COMPACT_LATEX = NO
+PAPER_TYPE = a4
+EXTRA_PACKAGES =
+LATEX_HEADER =
+LATEX_FOOTER =
+LATEX_EXTRA_FILES =
+PDF_HYPERLINKS = YES
+USE_PDFLATEX = YES
+LATEX_BATCHMODE = NO
+LATEX_HIDE_INDICES = NO
+LATEX_SOURCE_CODE = NO
+LATEX_BIB_STYLE = plain
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+GENERATE_RTF = NO
+RTF_OUTPUT = rtf
+COMPACT_RTF = NO
+RTF_HYPERLINKS = NO
+RTF_STYLESHEET_FILE =
+RTF_EXTENSIONS_FILE =
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+GENERATE_MAN = YES
+MAN_OUTPUT = man
+MAN_EXTENSION = .3
+MAN_LINKS = NO
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+GENERATE_XML = NO
+XML_OUTPUT = xml
+XML_SCHEMA =
+XML_DTD =
+XML_PROGRAMLISTING = YES
+#---------------------------------------------------------------------------
+# configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+GENERATE_DOCBOOK = NO
+DOCBOOK_OUTPUT = docbook
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+GENERATE_AUTOGEN_DEF = NO
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+GENERATE_PERLMOD = NO
+PERLMOD_LATEX = NO
+PERLMOD_PRETTY = YES
+PERLMOD_MAKEVAR_PREFIX =
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+ENABLE_PREPROCESSING = YES
+MACRO_EXPANSION = NO
+EXPAND_ONLY_PREDEF = NO
+SEARCH_INCLUDES = NO
+INCLUDE_PATH =
+INCLUDE_FILE_PATTERNS =
+PREDEFINED = __DOXYGEN__
+EXPAND_AS_DEFINED =
+SKIP_FUNCTION_MACROS = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+TAGFILES =
+GENERATE_TAGFILE =
+ALLEXTERNALS = NO
+EXTERNAL_GROUPS = NO
+EXTERNAL_PAGES = NO
+PERL_PATH = /usr/bin/perl
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+CLASS_DIAGRAMS = NO
+MSCGEN_PATH =
+HIDE_UNDOC_RELATIONS = YES
+HAVE_DOT = NO
+DOT_NUM_THREADS = 0
+DOT_FONTNAME = Helvetica
+DOT_FONTSIZE = 10
+DOT_FONTPATH =
+CLASS_GRAPH = YES
+COLLABORATION_GRAPH = YES
+GROUP_GRAPHS = YES
+UML_LOOK = NO
+UML_LIMIT_NUM_FIELDS = 10
+TEMPLATE_RELATIONS = NO
+INCLUDE_GRAPH = NO
+INCLUDED_BY_GRAPH = NO
+CALL_GRAPH = NO
+CALLER_GRAPH = NO
+GRAPHICAL_HIERARCHY = NO
+DIRECTORY_GRAPH = NO
+DOT_IMAGE_FORMAT = png
+INTERACTIVE_SVG = NO
+DOT_PATH =
+DOTFILE_DIRS =
+MSCFILE_DIRS =
+DOT_GRAPH_MAX_NODES = 50
+MAX_DOT_GRAPH_DEPTH = 0
+DOT_TRANSPARENT = NO
+DOT_MULTI_TARGETS = YES
+GENERATE_LEGEND = NO
+DOT_CLEANUP = YES
# - python 2.6 for json
# - argparse; either python 2.7, or install separately
+from __future__ import print_function
+from __future__ import unicode_literals
+
+import codecs
+import collections
import datetime
-import rfc822
-import urllib
+import email.utils
+try: # Python 3
+ from urllib.parse import quote
+except ImportError: # Python 2
+ from urllib import quote
import json
import argparse
import os
+import re
import sys
import subprocess
+import xml.sax.saxutils
+
+
+_ENCODING = 'UTF-8'
+_PAGES = {}
+
+
+if not hasattr(collections, 'OrderedDict'): # Python 2.6 or earlier
+ class _OrderedDict (dict):
+ "Just enough of a stub to get through Page._get_threads"
+ def __init__(self, *args, **kwargs):
+ super(_OrderedDict, self).__init__(*args, **kwargs)
+ self._keys = [] # record key order
+
+ def __setitem__(self, key, value):
+ super(_OrderedDict, self).__setitem__(key, value)
+ self._keys.append(key)
+
+ def __values__(self):
+ for key in self._keys:
+ yield self[key]
+
+
+ collections.OrderedDict = _OrderedDict
+
+
+def read_config(path=None, encoding=None):
+ "Read config from json file"
+ if not encoding:
+ encoding = _ENCODING
+ if path:
+ fp = open(path)
+ else:
+ nmbhome = os.getenv('NMBGIT', os.path.expanduser('~/.nmbug'))
+
+ # read only the first line from the pipe
+ sha1_bytes = subprocess.Popen(
+ ['git', '--git-dir', nmbhome, 'show-ref', '-s', 'config'],
+ stdout=subprocess.PIPE).stdout.readline()
+ sha1 = sha1_bytes.decode(encoding).rstrip()
+
+ fp_byte_stream = subprocess.Popen(
+ ['git', '--git-dir', nmbhome, 'cat-file', 'blob',
+ sha1+':status-config.json'],
+ stdout=subprocess.PIPE).stdout
+ fp = codecs.getreader(encoding=encoding)(stream=fp_byte_stream)
+
+ return json.load(fp)
+
+
+class Thread (list):
+ def __init__(self):
+ self.running_data = {}
+
+
+class Page (object):
+ def __init__(self, header=None, footer=None):
+ self.header = header
+ self.footer = footer
+
+ def write(self, database, views, stream=None):
+ if not stream:
+ try: # Python 3
+ byte_stream = sys.stdout.buffer
+ except AttributeError: # Python 2
+ byte_stream = sys.stdout
+ stream = codecs.getwriter(encoding=_ENCODING)(stream=byte_stream)
+ self._write_header(views=views, stream=stream)
+ for view in views:
+ self._write_view(database=database, view=view, stream=stream)
+ self._write_footer(views=views, stream=stream)
+
+ def _write_header(self, views, stream):
+ if self.header:
+ stream.write(self.header)
+
+ def _write_footer(self, views, stream):
+ if self.footer:
+ stream.write(self.footer)
+
+ def _write_view(self, database, view, stream):
+ if 'query-string' not in view:
+ query = view['query']
+ view['query-string'] = ' and '.join(query)
+ q = notmuch.Query(database, view['query-string'])
+ q.set_sort(notmuch.Query.SORT.OLDEST_FIRST)
+ threads = self._get_threads(messages=q.search_messages())
+ self._write_view_header(view=view, stream=stream)
+ self._write_threads(threads=threads, stream=stream)
+
+ def _get_threads(self, messages):
+ threads = collections.OrderedDict()
+ for message in messages:
+ thread_id = message.get_thread_id()
+ if thread_id in threads:
+ thread = threads[thread_id]
+ else:
+ thread = Thread()
+ threads[thread_id] = thread
+ thread.running_data, display_data = self._message_display_data(
+ running_data=thread.running_data, message=message)
+ thread.append(display_data)
+ return list(threads.values())
+
+ def _write_view_header(self, view, stream):
+ pass
+
+ def _write_threads(self, threads, stream):
+ for thread in threads:
+ for message_display_data in thread:
+ stream.write(
+ ('{date:10.10s} {from:20.20s} {subject:40.40s}\n'
+ '{message-id-term:>72}\n'
+ ).format(**message_display_data))
+ if thread != threads[-1]:
+ stream.write('\n')
+
+ def _message_display_data(self, running_data, message):
+ headers = ('thread-id', 'message-id', 'date', 'from', 'subject')
+ data = {}
+ for header in headers:
+ if header == 'thread-id':
+ value = message.get_thread_id()
+ elif header == 'message-id':
+ value = message.get_message_id()
+ data['message-id-term'] = 'id:"{0}"'.format(value)
+ elif header == 'date':
+ value = str(datetime.datetime.utcfromtimestamp(
+ message.get_date()).date())
+ else:
+ value = message.get_header(header)
+ if header == 'from':
+ (value, addr) = email.utils.parseaddr(value)
+ if not value:
+ value = addr.split('@')[0]
+ data[header] = value
+ next_running_data = data.copy()
+ for header, value in data.items():
+ if header in ['message-id', 'subject']:
+ continue
+ if value == running_data.get(header, None):
+ data[header] = ''
+ return (next_running_data, data)
+
+
+class HtmlPage (Page):
+ _slug_regexp = re.compile('\W+')
+
+ def _write_header(self, views, stream):
+ super(HtmlPage, self)._write_header(views=views, stream=stream)
+ stream.write('<ul>\n')
+ for view in views:
+ if 'id' not in view:
+ view['id'] = self._slug(view['title'])
+ stream.write(
+ '<li><a href="#{id}">{title}</a></li>\n'.format(**view))
+ stream.write('</ul>\n')
+
+ def _write_view_header(self, view, stream):
+ stream.write('<h3 id="{id}">{title}</h3>\n'.format(**view))
+ stream.write('<p>\n')
+ if 'comment' in view:
+ stream.write(view['comment'])
+ stream.write('\n')
+ for line in [
+ 'The view is generated from the following query:',
+ '</p>',
+ '<p>',
+ ' <code>',
+ view['query-string'],
+ ' </code>',
+ '</p>',
+ ]:
+ stream.write(line)
+ stream.write('\n')
+
+ def _write_threads(self, threads, stream):
+ if not threads:
+ return
+ stream.write('<table>\n')
+ for thread in threads:
+ stream.write(' <tbody>\n')
+ for message_display_data in thread:
+ stream.write((
+ ' <tr class="message-first">\n'
+ ' <td>{date}</td>\n'
+ ' <td><code>{message-id-term}</code></td>\n'
+ ' </tr>\n'
+ ' <tr class="message-last">\n'
+ ' <td>{from}</td>\n'
+ ' <td>{subject}</td>\n'
+ ' </tr>\n'
+ ).format(**message_display_data))
+ stream.write(' </tbody>\n')
+ if thread != threads[-1]:
+ stream.write(
+ ' <tbody><tr><td colspan="2"><br /></td></tr></tbody>\n')
+ stream.write('</table>\n')
+
+ def _message_display_data(self, *args, **kwargs):
+ running_data, display_data = super(
+ HtmlPage, self)._message_display_data(
+ *args, **kwargs)
+ if 'subject' in display_data and 'message-id' in display_data:
+ d = {
+ 'message-id': quote(display_data['message-id']),
+ 'subject': xml.sax.saxutils.escape(display_data['subject']),
+ }
+ display_data['subject'] = (
+ '<a href="http://mid.gmane.org/{message-id}">{subject}</a>'
+ ).format(**d)
+ for key in ['message-id', 'from']:
+ if key in display_data:
+ display_data[key] = xml.sax.saxutils.escape(display_data[key])
+ return (running_data, display_data)
+
+ def _slug(self, string):
+ return self._slug_regexp.sub('-', string)
+
+
+_PAGES['text'] = Page()
+_PAGES['html'] = HtmlPage(
+ header='''<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset={encoding}" />
+ <title>Notmuch Patches</title>
+ <style media="screen" type="text/css">
+ table {{
+ border-spacing: 0;
+ }}
+ tr.message-first td {{
+ padding-top: {inter_message_padding};
+ }}
+ tr.message-last td {{
+ padding-bottom: {inter_message_padding};
+ }}
+ td {{
+ padding-left: {border_radius};
+ padding-right: {border_radius};
+ }}
+ tr:first-child td:first-child {{
+ border-top-left-radius: {border_radius};
+ }}
+ tr:first-child td:last-child {{
+ border-top-right-radius: {border_radius};
+ }}
+ tr:last-child td:first-child {{
+ border-bottom-left-radius: {border_radius};
+ }}
+ tr:last-child td:last-child {{
+ border-bottom-right-radius: {border_radius};
+ }}
+ tbody:nth-child(4n+1) tr td {{
+ background-color: #ffd96e;
+ }}
+ tbody:nth-child(4n+3) tr td {{
+ background-color: #bce;
+ }}
+ </style>
+</head>
+<body>
+<h2>Notmuch Patches</h2>
+<p>
+Generated: {date}<br />
+For more infomation see <a href="http://notmuchmail.org/nmbug">nmbug</a>
+</p>
+<h3>Views</h3>
+'''.format(date=datetime.datetime.utcnow().date(),
+ encoding=_ENCODING,
+ inter_message_padding='0.25em',
+ border_radius='0.5em'),
+ footer='</body>\n</html>\n',
+ )
-# parse command line arguments
parser = argparse.ArgumentParser()
parser.add_argument('--text', help='output plain text format',
action='store_true')
-parser.add_argument('--config', help='load config from given file')
+parser.add_argument('--config', help='load config from given file',
+ metavar='PATH')
parser.add_argument('--list-views', help='list views',
action='store_true')
-parser.add_argument('--get-query', help='get query for view')
+parser.add_argument('--get-query', help='get query for view',
+ metavar='VIEW')
args = parser.parse_args()
-# read config from json file
-
-if args.config != None:
- fp = open(args.config)
-else:
- nmbhome = os.getenv('NMBGIT', os.path.expanduser('~/.nmbug'))
-
- # read only the first line from the pipe
- sha1 = subprocess.Popen(['git', '--git-dir', nmbhome,
- 'show-ref', '-s', 'config'],
- stdout=subprocess.PIPE).stdout.readline()
-
- sha1 = sha1.rstrip()
-
- fp = subprocess.Popen(['git', '--git-dir', nmbhome,
- 'cat-file', 'blob', sha1+':status-config.json'],
- stdout=subprocess.PIPE).stdout
-
-config = json.load(fp)
+config = read_config(path=args.config)
if args.list_views:
for view in config['views']:
- print view['title']
+ print(view['title'])
sys.exit(0)
elif args.get_query != None:
for view in config['views']:
if args.get_query == view['title']:
- print ' and '.join(view['query'])
+ print(' and '.join(view['query']))
sys.exit(0)
else:
# only import notmuch if needed
import notmuch
if args.text:
- output_format = 'text'
+ page = _PAGES['text']
else:
- output_format = 'html'
-
-class Thread:
- def __init__(self, last, lines):
- self.last = last
- self.lines = lines
-
- def join_utf8_with_newlines(self):
- return '\n'.join( (line.encode('utf-8') for line in self.lines) )
-
-def output_with_separator(threadlist, sep):
- outputs = (thread.join_utf8_with_newlines() for thread in threadlist)
- print sep.join(outputs)
-
-headers = ['date', 'from', 'subject']
-
-def print_view(title, query, comment):
-
- query_string = ' and '.join(query)
- q_new = notmuch.Query(db, query_string)
- q_new.set_sort(notmuch.Query.SORT.OLDEST_FIRST)
-
- last_thread_id = ''
- threads = {}
- threadlist = []
- out = {}
- last = None
- lines = None
-
- if output_format == 'html':
- print '<h3><a name="%s" />%s</h3>' % (title, title)
- print comment
- print 'The view is generated from the following query:'
- print '<blockquote>'
- print query_string
- print '</blockquote>'
- print '<table>\n'
-
- for m in q_new.search_messages():
-
- thread_id = m.get_thread_id()
-
- if thread_id != last_thread_id:
- if threads.has_key(thread_id):
- last = threads[thread_id].last
- lines = threads[thread_id].lines
- else:
- last = {}
- lines = []
- thread = Thread(last, lines)
- threads[thread_id] = thread
- for h in headers:
- last[h] = ''
- threadlist.append(thread)
- last_thread_id = thread_id
-
- for header in headers:
- val = m.get_header(header)
-
- if header == 'date':
- val = str.join(' ', val.split(None)[1:4])
- val = str(datetime.datetime.strptime(val, '%d %b %Y').date())
- elif header == 'from':
- (val, addr) = rfc822.parseaddr(val)
- if val == '':
- val = addr.split('@')[0]
-
- if header != 'subject' and last[header] == val:
- out[header] = ''
- else:
- out[header] = val
- last[header] = val
-
- mid = m.get_message_id()
- out['id'] = 'id:"%s"' % mid
-
- if output_format == 'html':
-
- out['subject'] = '<a href="http://mid.gmane.org/%s">%s</a>' \
- % (urllib.quote(mid), out['subject'])
-
- lines.append(' <tr><td>%s' % out['date'])
- lines.append('</td><td>%s' % out['id'])
- lines.append('</td></tr>')
- lines.append(' <tr><td>%s' % out['from'])
- lines.append('</td><td>%s' % out['subject'])
- lines.append('</td></tr>')
- else:
- lines.append('%(date)-10.10s %(from)-20.20s %(subject)-40.40s\n%(id)72s' % out)
-
- if output_format == 'html':
- output_with_separator(threadlist,
- '\n<tr><td colspan="2"><br /></td></tr>\n')
- print '</table>'
- else:
- output_with_separator(threadlist, '\n\n')
-
-# main program
-
-db = notmuch.Database(mode=notmuch.Database.MODE.READ_WRITE)
-
-if output_format == 'html':
- print '''<?xml version="1.0" encoding="utf-8" ?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-<title>Notmuch Patches</title>
-</head>
-<body>'''
- print '<h2>Notmuch Patches</h2>'
- print 'Generated: %s<br />' % datetime.datetime.utcnow().date()
- print 'For more infomation see <a href="http://notmuchmail.org/nmbug">nmbug</a>'
-
- print '<h3>Views</h3>'
- print '<ul>'
- for view in config['views']:
- print '<li><a href="#%(title)s">%(title)s</a></li>' % view
- print '</ul>'
-
-for view in config['views']:
- print_view(**view)
+ page = _PAGES['html']
-if output_format == 'html':
- print '</body>\n</html>'
+db = notmuch.Database(mode=notmuch.Database.MODE.READ_ONLY)
+page.write(database=db, views=config['views'])
# the byte compiler may load an old .elc file when processing a
# "require" or we may fail to rebuild a .elc that depended on a macro
# from an updated file.
+ifeq ($(HAVE_EMACS),1)
$(dir)/.eldeps: $(dir)/Makefile.local $(dir)/make-deps.el $(emacs_sources)
$(call quiet,EMACS) --directory emacs -batch -l make-deps.el \
-f batch-make-deps $(emacs_sources) > $@.tmp && \
(cmp -s $@.tmp $@ || mv $@.tmp $@)
-include $(dir)/.eldeps
+endif
CLEAN+=$(dir)/.eldeps $(dir)/.eldeps.tmp
+ifeq ($(HAVE_EMACS),1)
%.elc: %.el $(global_deps)
$(call quiet,EMACS) --directory emacs -batch -f batch-byte-compile $<
+endif
ifeq ($(WITH_EMACS),1)
ifeq ($(HAVE_EMACS),1)
all: $(emacs_bytecode)
+install-emacs: $(emacs_bytecode)
endif
install: install-emacs
"Run notmuch and display saved searches, known tags, etc."
(interactive)
+ (notmuch-assert-cli-sane)
;; This may cause a window configuration change, so if the
;; auto-refresh hook is already installed, avoid recursive refresh.
(let ((notmuch-hello-auto-refresh nil))
(notmuch-check-exit-status status (cons notmuch-command args) output)
output)))
+(defvar notmuch--cli-sane-p nil
+ "Cache whether the CLI seems to be configured sanely.")
+
+(defun notmuch-cli-sane-p ()
+ "Return t if the cli seems to be configured sanely."
+ (unless notmuch--cli-sane-p
+ (let ((status (call-process notmuch-command nil nil nil
+ "config" "get" "user.primary_email")))
+ (setq notmuch--cli-sane-p (= status 0))))
+ notmuch--cli-sane-p)
+
+(defun notmuch-assert-cli-sane ()
+ (unless (notmuch-cli-sane-p)
+ (notmuch-logged-error
+ "notmuch cli seems misconfigured or unconfigured."
+"Perhaps you haven't run \"notmuch setup\" yet? Try running this
+on the command line, and then retry your notmuch command")))
+
(defun notmuch-version ()
"Return a string with the notmuch version number."
(let ((long-string
"Given a prefix key code, return a human-readable string representation.
This is basically just `format-kbd-macro' but we also convert ESC to M-."
- (let ((desc (format-kbd-macro (vector key))))
+ (let* ((key-vector (if (vectorp key) key (vector key)))
+ (desc (format-kbd-macro key-vector)))
(if (string= desc "ESC")
"M-"
(concat desc " "))))
(set-buffer-modified-p nil)
(view-buffer (current-buffer) 'kill-buffer-if-not-modified))))
+(defun notmuch-subkeymap-help ()
+ "Show help for a subkeymap."
+ (interactive)
+ (let* ((key (this-command-keys-vector))
+ (prefix (make-vector (1- (length key)) nil))
+ (i 0))
+ (while (< i (length prefix))
+ (aset prefix i (aref key i))
+ (setq i (1+ i)))
+
+ (let* ((subkeymap (key-binding prefix))
+ (ua-keys (where-is-internal 'universal-argument nil t))
+ (prefix-string (notmuch-prefix-key-description prefix))
+ (desc-alist (notmuch-describe-keymap subkeymap ua-keys subkeymap prefix-string))
+ (desc-list (mapcar (lambda (arg) (concat (car arg) "\t" (cdr arg))) desc-alist))
+ (desc (mapconcat #'identity desc-list "\n")))
+ (with-help-window (help-buffer)
+ (with-current-buffer standard-output
+ (insert "\nPress 'q' to quit this window.\n\n")
+ (insert desc)))
+ (pop-to-buffer (help-buffer)))))
+
(defvar notmuch-buffer-refresh-function nil
"Function to call to refresh the current buffer.")
(make-variable-buffer-local 'notmuch-buffer-refresh-function)
(if (>= emacs-major-version 24)
(defadvice mm-shr (before load-gnus-arts activate)
(require 'gnus-art nil t)
- (ad-disable-advice 'mm-shr 'before 'load-gnus-arts)))
+ (ad-disable-advice 'mm-shr 'before 'load-gnus-arts)
+ (ad-activate 'mm-shr)))
(defun notmuch-mm-display-part-inline (msg part nth content-type process-crypto)
"Use the mm-decode/mm-view functions to display a part in the
(defvar notmuch-mua-sender-history nil)
+;; Workaround: Running `ido-completing-read' in emacs 23.1, 23.2 and 23.3
+;; without some explicit initialization fill freeze the operation.
+;; Hence, we advice `ido-completing-read' to ensure required initialization
+;; is done.
+(if (and (= emacs-major-version 23) (< emacs-minor-version 4))
+ (defadvice ido-completing-read (before notmuch-ido-mode-init activate)
+ (ido-init-completion-maps)
+ (add-hook 'minibuffer-setup-hook 'ido-minibuffer-setup)
+ (add-hook 'choose-completion-string-functions
+ 'ido-choose-completion-string)
+ (ad-disable-advice 'ido-completing-read 'before 'notmuch-ido-mode-init)
+ (ad-activate 'ido-completing-read)))
+
(defun notmuch-mua-prompt-for-sender ()
(interactive)
(let (name addresses one-name-only)
(defcustom notmuch-show-stash-mlarchive-link-alist
'(("Gmane" . "http://mid.gmane.org/")
("MARC" . "http://marc.info/?i=")
- ("Mail Archive, The" . "http://mail-archive.com/search?l=mid&q=")
+ ("Mail Archive, The" . "http://mid.mail-archive.com/")
("LKML" . "http://lkml.kernel.org/r/")
;; FIXME: can these services be searched by `Message-Id' ?
;; ("MarkMail" . "http://markmail.org/")
(define-key map "t" 'notmuch-show-stash-to)
(define-key map "l" 'notmuch-show-stash-mlarchive-link)
(define-key map "L" 'notmuch-show-stash-mlarchive-link-and-go)
+ (define-key map "?" 'notmuch-subkeymap-help)
map)
"Submap for stash commands")
(fset 'notmuch-show-stash-map notmuch-show-stash-map)
(define-key map "v" 'notmuch-show-view-part)
(define-key map "o" 'notmuch-show-interactively-view-part)
(define-key map "|" 'notmuch-show-pipe-part)
+ (define-key map "?" 'notmuch-subkeymap-help)
map)
"Submap for part commands")
(fset 'notmuch-show-part-map notmuch-show-part-map)
(dolist (format (cdr formats) tag)
(setq tag (eval format))))))))
-(defun notmuch-tag-format-tags (tags)
+(defun notmuch-tag-format-tags (tags &optional face)
"Return a string representing formatted TAGS."
- (notmuch-combine-face-text-property-string
- (mapconcat #'identity
- ;; nil indicated that the tag was deliberately hidden
- (delq nil (mapcar #'notmuch-tag-format-tag tags))
- " ")
- 'notmuch-tag-face
- t))
+ (let ((face (or face 'notmuch-tag-face)))
+ (notmuch-combine-face-text-property-string
+ (mapconcat #'identity
+ ;; nil indicated that the tag was deliberately hidden
+ (delq nil (mapcar #'notmuch-tag-format-tag tags))
+ " ")
+ face
+ t)))
(defcustom notmuch-before-tag-hook nil
"Hooks that are run before tags of a message are modified.
:group 'notmuch-tree)
;; Faces for messages that match the query.
-(defface notmuch-tree-match-date-face
+(defface notmuch-tree-match-face
'((t :inherit default))
+ "Default face used in tree mode face for matching messages"
+ :group 'notmuch-tree
+ :group 'notmuch-faces)
+
+(defface notmuch-tree-match-date-face
+ nil
"Face used in tree mode for the date in messages matching the query."
:group 'notmuch-tree
:group 'notmuch-faces)
:group 'notmuch-faces)
(defface notmuch-tree-match-subject-face
- '((t :inherit default))
+ nil
"Face used in tree mode for the subject in messages matching the query."
:group 'notmuch-tree
:group 'notmuch-faces)
(defface notmuch-tree-match-tree-face
- '((t :inherit default))
+ nil
"Face used in tree mode for the thread tree block graphics in messages matching the query."
:group 'notmuch-tree
:group 'notmuch-faces)
:group 'notmuch-faces)
;; Faces for messages that do not match the query.
-(defface notmuch-tree-no-match-date-face
+(defface notmuch-tree-no-match-face
'((t (:foreground "gray")))
+ "Default face used in tree mode face for non-matching messages"
+ :group 'notmuch-tree
+ :group 'notmuch-faces)
+
+(defface notmuch-tree-no-match-date-face
+ nil
"Face used in tree mode for non-matching dates."
:group 'notmuch-tree
:group 'notmuch-faces)
(defface notmuch-tree-no-match-subject-face
- '((t (:foreground "gray")))
+ nil
"Face used in tree mode for non-matching subjects."
:group 'notmuch-tree
:group 'notmuch-faces)
(defface notmuch-tree-no-match-tree-face
- '((t (:foreground "gray")))
+ nil
"Face used in tree mode for the thread tree block graphics in messages matching the query."
:group 'notmuch-tree
:group 'notmuch-faces)
(defface notmuch-tree-no-match-author-face
- '((t (:foreground "gray")))
+ nil
"Face used in tree mode for the date in messages matching the query."
:group 'notmuch-tree
:group 'notmuch-faces)
(defface notmuch-tree-no-match-tag-face
- '((t (:foreground "gray")))
+ nil
"Face used in tree mode face for non-matching tags."
:group 'notmuch-tree
:group 'notmuch-faces)
"Return the tags of the current message."
(notmuch-tree-get-prop :tags))
-(defun notmuch-tree-get-message-id ()
+(defun notmuch-tree-get-message-id (&optional bare)
"Return the message id of the current message."
(let ((id (notmuch-tree-get-prop :id)))
(if id
- (notmuch-id-to-query id)
+ (if bare
+ id
+ (notmuch-id-to-query id))
nil)))
(defun notmuch-tree-get-match ()
(face (if match
'notmuch-tree-match-tag-face
'notmuch-tree-no-match-tag-face)))
- (propertize (format format-string
- (mapconcat #'identity tags ", "))
- 'face face))))))
-
+ (format format-string (notmuch-tag-format-tags tags face)))))))
(defun notmuch-tree-format-field-list (field-list msg)
"Format fields of MSG according to FIELD-LIST and return string"
- (let (result-string)
+ (let ((face (if (plist-get msg :match)
+ 'notmuch-tree-match-face
+ 'notmuch-tree-no-match-face))
+ (result-string))
(dolist (spec field-list result-string)
(let ((field-string (notmuch-tree-format-field (car spec) (cdr spec) msg)))
- (setq result-string (concat result-string field-string))))))
+ (setq result-string (concat result-string field-string))))
+ (notmuch-combine-face-text-property-string result-string face t)))
(defun notmuch-tree-insert-msg (msg)
"Insert the message MSG according to notmuch-tree-result-format"
(defvar notmuch-search-stash-map
(let ((map (make-sparse-keymap)))
(define-key map "i" 'notmuch-search-stash-thread-id)
+ (define-key map "?" 'notmuch-subkeymap-help)
map)
"Submap for stash commands")
(fset 'notmuch-search-stash-map notmuch-search-stash-map)
const char *
notmuch_message_get_header (notmuch_message_t *message, const char *header)
{
- std::string value;
+ try {
+ std::string value;
- /* Fetch header from the appropriate xapian value field if
- * available */
- if (strcasecmp (header, "from") == 0)
- value = message->doc.get_value (NOTMUCH_VALUE_FROM);
- else if (strcasecmp (header, "subject") == 0)
- value = message->doc.get_value (NOTMUCH_VALUE_SUBJECT);
- else if (strcasecmp (header, "message-id") == 0)
- value = message->doc.get_value (NOTMUCH_VALUE_MESSAGE_ID);
+ /* Fetch header from the appropriate xapian value field if
+ * available */
+ if (strcasecmp (header, "from") == 0)
+ value = message->doc.get_value (NOTMUCH_VALUE_FROM);
+ else if (strcasecmp (header, "subject") == 0)
+ value = message->doc.get_value (NOTMUCH_VALUE_SUBJECT);
+ else if (strcasecmp (header, "message-id") == 0)
+ value = message->doc.get_value (NOTMUCH_VALUE_MESSAGE_ID);
- if (!value.empty())
- return talloc_strdup (message, value.c_str ());
+ if (!value.empty())
+ return talloc_strdup (message, value.c_str ());
+
+ } catch (Xapian::Error &error) {
+ fprintf (stderr, "A Xapian exception occurred when reading header: %s\n",
+ error.get_msg().c_str());
+ message->notmuch->exception_reported = TRUE;
+ return NULL;
+ }
/* Otherwise fall back to parsing the file */
_notmuch_message_ensure_message_file (message);
try {
value = message->doc.get_value (NOTMUCH_VALUE_TIMESTAMP);
} catch (Xapian::Error &error) {
- INTERNAL_ERROR ("Failed to read timestamp value from document.");
+ fprintf (stderr, "A Xapian exception occurred when reading date: %s\n",
+ error.get_msg().c_str());
+ message->notmuch->exception_reported = TRUE;
return 0;
}
* Author: Carl Worth <cworth@cworth.org>
*/
+/**
+ * @defgroup notmuch The notmuch API
+ *
+ * Not much of an email library, (just index and search)
+ *
+ * @{
+ */
+
#ifndef NOTMUCH_H
#define NOTMUCH_H
+#ifndef __DOXYGEN__
+
#ifdef __cplusplus
# define NOTMUCH_BEGIN_DECLS extern "C" {
# define NOTMUCH_END_DECLS }
#define LIBNOTMUCH_MINOR_VERSION 1
#define LIBNOTMUCH_MICRO_VERSION 0
-/*
+#endif /* __DOXYGEN__ */
+
+/**
* Check the version of the notmuch library being compiled against.
*
* Return true if the library being compiled against is of the
* specified version or above. For example:
*
+ * @code
* #if LIBNOTMUCH_CHECK_VERSION(3, 1, 0)
* (code requiring libnotmuch 3.1.0 or above)
* #endif
+ * @endcode
*
- * LIBNOTMUCH_CHECK_VERSION has been defined since version 3.1.0; you
- * can use #if !defined(NOTMUCH_CHECK_VERSION) to check for versions
- * prior to that.
+ * LIBNOTMUCH_CHECK_VERSION has been defined since version 3.1.0; to
+ * check for versions prior to that, use:
+ *
+ * @code
+ * #if !defined(NOTMUCH_CHECK_VERSION)
+ * (code requiring libnotmuch prior to 3.1.0)
+ * #endif
+ * @endcode
*/
#define LIBNOTMUCH_CHECK_VERSION (major, minor, micro) \
(LIBNOTMUCH_MAJOR_VERSION > (major) || \
(LIBNOTMUCH_MAJOR_VERSION == (major) && LIBNOTMUCH_MINOR_VERSION == (minor) && \
LIBNOTMUCH_MICRO_VERSION >= (micro)))
+/**
+ * Notmuch boolean type.
+ */
typedef int notmuch_bool_t;
-/* Status codes used for the return values of most functions.
+/**
+ * Status codes used for the return values of most functions.
*
* A zero value (NOTMUCH_STATUS_SUCCESS) indicates that the function
- * completed without error. Any other value indicates an error as
- * follows:
- *
- * NOTMUCH_STATUS_SUCCESS: No error occurred.
- *
- * NOTMUCH_STATUS_OUT_OF_MEMORY: Out of memory
- *
- * XXX: We don't really want to expose this lame XAPIAN_EXCEPTION
- * value. Instead we should map to things like DATABASE_LOCKED or
- * whatever.
- *
- * NOTMUCH_STATUS_READ_ONLY_DATABASE: An attempt was made to write to
- * a database opened in read-only mode.
- *
- * NOTMUCH_STATUS_XAPIAN_EXCEPTION: A Xapian exception occurred
- *
- * NOTMUCH_STATUS_FILE_ERROR: An error occurred trying to read or
- * write to a file (this could be file not found, permission
- * denied, etc.)
- *
- * NOTMUCH_STATUS_FILE_NOT_EMAIL: A file was presented that doesn't
- * appear to be an email message.
- *
- * NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID: A file contains a message ID
- * that is identical to a message already in the database.
- *
- * NOTMUCH_STATUS_NULL_POINTER: The user erroneously passed a NULL
- * pointer to a notmuch function.
- *
- * NOTMUCH_STATUS_TAG_TOO_LONG: A tag value is too long (exceeds
- * NOTMUCH_TAG_MAX)
- *
- * NOTMUCH_STATUS_UNBALANCED_FREEZE_THAW: The notmuch_message_thaw
- * function has been called more times than notmuch_message_freeze.
- *
- * NOTMUCH_STATUS_UNBALANCED_ATOMIC: notmuch_database_end_atomic has
- * been called more times than notmuch_database_begin_atomic.
- *
- * And finally:
- *
- * NOTMUCH_STATUS_LAST_STATUS: Not an actual status value. Just a way
- * to find out how many valid status values there are.
+ * completed without error. Any other value indicates an error.
*/
typedef enum _notmuch_status {
+ /**
+ * No error occurred.
+ */
NOTMUCH_STATUS_SUCCESS = 0,
+ /**
+ * Out of memory.
+ */
NOTMUCH_STATUS_OUT_OF_MEMORY,
+ /**
+ * An attempt was made to write to a database opened in read-only
+ * mode.
+ */
NOTMUCH_STATUS_READ_ONLY_DATABASE,
+ /**
+ * A Xapian exception occurred.
+ */
NOTMUCH_STATUS_XAPIAN_EXCEPTION,
+ /**
+ * An error occurred trying to read or write to a file (this could
+ * be file not found, permission denied, etc.)
+ *
+ * @todo We don't really want to expose this lame XAPIAN_EXCEPTION
+ * value. Instead we should map to things like DATABASE_LOCKED or
+ * whatever.
+ */
NOTMUCH_STATUS_FILE_ERROR,
+ /**
+ * A file was presented that doesn't appear to be an email
+ * message.
+ */
NOTMUCH_STATUS_FILE_NOT_EMAIL,
+ /**
+ * A file contains a message ID that is identical to a message
+ * already in the database.
+ */
NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID,
+ /**
+ * The user erroneously passed a NULL pointer to a notmuch
+ * function.
+ */
NOTMUCH_STATUS_NULL_POINTER,
+ /**
+ * A tag value is too long (exceeds NOTMUCH_TAG_MAX).
+ */
NOTMUCH_STATUS_TAG_TOO_LONG,
+ /**
+ * The notmuch_message_thaw function has been called more times
+ * than notmuch_message_freeze.
+ */
NOTMUCH_STATUS_UNBALANCED_FREEZE_THAW,
+ /**
+ * notmuch_database_end_atomic has been called more times than
+ * notmuch_database_begin_atomic.
+ */
NOTMUCH_STATUS_UNBALANCED_ATOMIC,
+ /**
+ * The operation is not supported.
+ */
NOTMUCH_STATUS_UNSUPPORTED_OPERATION,
-
+ /**
+ * Not an actual status value. Just a way to find out how many
+ * valid status values there are.
+ */
NOTMUCH_STATUS_LAST_STATUS
} notmuch_status_t;
-/* Get a string representation of a notmuch_status_t value.
+/**
+ * Get a string representation of a notmuch_status_t value.
*
* The result is read-only.
*/
/* Various opaque data types. For each notmuch_<foo>_t see the various
* notmuch_<foo> functions below. */
+#ifndef __DOXYGEN__
typedef struct _notmuch_database notmuch_database_t;
typedef struct _notmuch_query notmuch_query_t;
typedef struct _notmuch_threads notmuch_threads_t;
typedef struct _notmuch_tags notmuch_tags_t;
typedef struct _notmuch_directory notmuch_directory_t;
typedef struct _notmuch_filenames notmuch_filenames_t;
+#endif /* __DOXYGEN__ */
-/* Create a new, empty notmuch database located at 'path'.
+/**
+ * Create a new, empty notmuch database located at 'path'.
*
* The path should be a top-level directory to a collection of
* plain-text email messages (one message per file). This call will
notmuch_status_t
notmuch_database_create (const char *path, notmuch_database_t **database);
+/**
+ * Database open mode for notmuch_database_open.
+ */
typedef enum {
+ /**
+ * Open database for reading only.
+ */
NOTMUCH_DATABASE_MODE_READ_ONLY = 0,
+ /**
+ * Open database for reading and writing.
+ */
NOTMUCH_DATABASE_MODE_READ_WRITE
} notmuch_database_mode_t;
-/* Open an existing notmuch database located at 'path'.
+/**
+ * Open an existing notmuch database located at 'path'.
*
* The database should have been created at some time in the past,
* (not necessarily by this process), by calling
notmuch_database_mode_t mode,
notmuch_database_t **database);
-/* Close the given notmuch database.
+/**
+ * Close the given notmuch database.
*
* After notmuch_database_close has been called, calls to other
* functions on objects derived from this database may either behave
void
notmuch_database_close (notmuch_database_t *database);
-/* A callback invoked by notmuch_database_compact to notify the user
+/**
+ * A callback invoked by notmuch_database_compact to notify the user
* of the progress of the compaction process.
*/
typedef void (*notmuch_compact_status_cb_t)(const char *message, void *closure);
-/* Compact a notmuch database, backing up the original database to the
+/**
+ * Compact a notmuch database, backing up the original database to the
* given path.
*
* The database will be opened with NOTMUCH_DATABASE_MODE_READ_WRITE
notmuch_compact_status_cb_t status_cb,
void *closure);
-/* Destroy the notmuch database, closing it if necessary and freeing
+/**
+ * Destroy the notmuch database, closing it if necessary and freeing
* all associated resources.
*/
void
notmuch_database_destroy (notmuch_database_t *database);
-/* Return the database path of the given database.
+/**
+ * Return the database path of the given database.
*
* The return value is a string owned by notmuch so should not be
- * modified nor freed by the caller. */
+ * modified nor freed by the caller.
+ */
const char *
notmuch_database_get_path (notmuch_database_t *database);
-/* Return the database format version of the given database. */
+/**
+ * Return the database format version of the given database.
+ */
unsigned int
notmuch_database_get_version (notmuch_database_t *database);
-/* Does this database need to be upgraded before writing to it?
+/**
+ * Does this database need to be upgraded before writing to it?
*
* If this function returns TRUE then no functions that modify the
* database (notmuch_database_add_message, notmuch_message_add_tag,
* notmuch_directory_set_mtime, etc.) will work unless the function
- * notmuch_database_upgrade is called successfully first. */
+ * notmuch_database_upgrade is called successfully first.
+ */
notmuch_bool_t
notmuch_database_needs_upgrade (notmuch_database_t *database);
-/* Upgrade the current database.
+/**
+ * Upgrade the current database.
*
* After opening a database in read-write mode, the client should
* check if an upgrade is needed (notmuch_database_needs_upgrade) and
double progress),
void *closure);
-/* Begin an atomic database operation.
+/**
+ * Begin an atomic database operation.
*
* Any modifications performed between a successful begin and a
* notmuch_database_end_atomic will be applied to the database
notmuch_status_t
notmuch_database_begin_atomic (notmuch_database_t *notmuch);
-/* Indicate the end of an atomic database operation.
+/**
+ * Indicate the end of an atomic database operation.
*
* Return value:
*
notmuch_status_t
notmuch_database_end_atomic (notmuch_database_t *notmuch);
-/* Retrieve a directory object from the database for 'path'.
+/**
+ * Retrieve a directory object from the database for 'path'.
*
* Here, 'path' should be a path relative to the path of 'database'
* (see notmuch_database_get_path), or else should be an absolute path
* If this directory object does not exist in the database, this
* returns NOTMUCH_STATUS_SUCCESS and sets *directory to NULL.
*
+ * Otherwise the returned directory object is owned by the database
+ * and as such, will only be valid until notmuch_database_destroy is
+ * called.
+ *
* Return value:
*
* NOTMUCH_STATUS_SUCCESS: Successfully retrieved directory.
const char *path,
notmuch_directory_t **directory);
-/* Add a new message to the given notmuch database or associate an
+/**
+ * Add a new message to the given notmuch database or associate an
* additional filename with an existing message.
*
* Here, 'filename' should be a path relative to the path of
const char *filename,
notmuch_message_t **message);
-/* Remove a message filename from the given notmuch database. If the
+/**
+ * Remove a message filename from the given notmuch database. If the
* message has no more filenames, remove the message.
*
* If the same message (as determined by the message ID) is still
notmuch_database_remove_message (notmuch_database_t *database,
const char *filename);
-/* Find a message with the given message_id.
+/**
+ * Find a message with the given message_id.
*
* If a message with the given message_id is found then, on successful return
* (NOTMUCH_STATUS_SUCCESS) '*message' will be initialized to a message
const char *message_id,
notmuch_message_t **message);
-/* Find a message with the given filename.
+/**
+ * Find a message with the given filename.
*
* If the database contains a message with the given filename then, on
* successful return (NOTMUCH_STATUS_SUCCESS) '*message' will be initialized to
const char *filename,
notmuch_message_t **message);
-/* Return a list of all tags found in the database.
+/**
+ * Return a list of all tags found in the database.
*
* This function creates a list of all tags found in the database. The
* resulting list contains all tags from all messages found in the database.
notmuch_tags_t *
notmuch_database_get_all_tags (notmuch_database_t *db);
-/* Create a new query for 'database'.
+/**
+ * Create a new query for 'database'.
*
* Here, 'database' should be an open database, (see
* notmuch_database_open and notmuch_database_create).
notmuch_query_create (notmuch_database_t *database,
const char *query_string);
-/* Sort values for notmuch_query_set_sort */
+/**
+ * Sort values for notmuch_query_set_sort.
+ */
typedef enum {
+ /**
+ * Oldest first.
+ */
NOTMUCH_SORT_OLDEST_FIRST,
+ /**
+ * Newest first.
+ */
NOTMUCH_SORT_NEWEST_FIRST,
+ /**
+ * Sort by message-id.
+ */
NOTMUCH_SORT_MESSAGE_ID,
+ /**
+ * Do not sort.
+ */
NOTMUCH_SORT_UNSORTED
} notmuch_sort_t;
-/* Return the query_string of this query. See notmuch_query_create. */
+/**
+ * Return the query_string of this query. See notmuch_query_create.
+ */
const char *
notmuch_query_get_query_string (notmuch_query_t *query);
-/* Exclude values for notmuch_query_set_omit_excluded. The strange
+/**
+ * Exclude values for notmuch_query_set_omit_excluded. The strange
* order is to maintain backward compatibility: the old FALSE/TRUE
* options correspond to the new
* NOTMUCH_EXCLUDE_FLAG/NOTMUCH_EXCLUDE_TRUE options.
NOTMUCH_EXCLUDE_ALL
} notmuch_exclude_t;
-/* Specify whether to omit excluded results or simply flag them. By
+/**
+ * Specify whether to omit excluded results or simply flag them. By
* default, this is set to TRUE.
*
* If set to TRUE or ALL, notmuch_query_search_messages will omit excluded
notmuch_query_set_omit_excluded (notmuch_query_t *query,
notmuch_exclude_t omit_excluded);
-/* Specify the sorting desired for this query. */
+/**
+ * Specify the sorting desired for this query.
+ */
void
notmuch_query_set_sort (notmuch_query_t *query, notmuch_sort_t sort);
-/* Return the sort specified for this query. See notmuch_query_set_sort. */
+/**
+ * Return the sort specified for this query. See
+ * notmuch_query_set_sort.
+ */
notmuch_sort_t
notmuch_query_get_sort (notmuch_query_t *query);
-/* Add a tag that will be excluded from the query results by default.
+/**
+ * Add a tag that will be excluded from the query results by default.
* This exclusion will be overridden if this tag appears explicitly in
- * the query. */
+ * the query.
+ */
void
notmuch_query_add_tag_exclude (notmuch_query_t *query, const char *tag);
-/* Execute a query for threads, returning a notmuch_threads_t object
+/**
+ * Execute a query for threads, returning a notmuch_threads_t object
* which can be used to iterate over the results. The returned threads
* object is owned by the query and as such, will only be valid until
* notmuch_query_destroy.
notmuch_threads_t *
notmuch_query_search_threads (notmuch_query_t *query);
-/* Execute a query for messages, returning a notmuch_messages_t object
+/**
+ * Execute a query for messages, returning a notmuch_messages_t object
* which can be used to iterate over the results. The returned
* messages object is owned by the query and as such, will only be
* valid until notmuch_query_destroy.
notmuch_messages_t *
notmuch_query_search_messages (notmuch_query_t *query);
-/* Destroy a notmuch_query_t along with any associated resources.
+/**
+ * Destroy a notmuch_query_t along with any associated resources.
*
* This will in turn destroy any notmuch_threads_t and
* notmuch_messages_t objects generated by this query, (and in
void
notmuch_query_destroy (notmuch_query_t *query);
-/* Is the given 'threads' iterator pointing at a valid thread.
+/**
+ * Is the given 'threads' iterator pointing at a valid thread.
*
* When this function returns TRUE, notmuch_threads_get will return a
* valid object. Whereas when this function returns FALSE,
* notmuch_threads_get will return NULL.
*
+ * If passed a NULL pointer, this function returns FALSE
+ *
* See the documentation of notmuch_query_search_threads for example
* code showing how to iterate over a notmuch_threads_t object.
*/
notmuch_bool_t
notmuch_threads_valid (notmuch_threads_t *threads);
-/* Get the current thread from 'threads' as a notmuch_thread_t.
+/**
+ * Get the current thread from 'threads' as a notmuch_thread_t.
*
* Note: The returned thread belongs to 'threads' and has a lifetime
* identical to it (and the query to which it belongs).
notmuch_thread_t *
notmuch_threads_get (notmuch_threads_t *threads);
-/* Move the 'threads' iterator to the next thread.
+/**
+ * Move the 'threads' iterator to the next thread.
*
* If 'threads' is already pointing at the last thread then the
* iterator will be moved to a point just beyond that last thread,
void
notmuch_threads_move_to_next (notmuch_threads_t *threads);
-/* Destroy a notmuch_threads_t object.
+/**
+ * Destroy a notmuch_threads_t object.
*
* It's not strictly necessary to call this function. All memory from
* the notmuch_threads_t object will be reclaimed when the
void
notmuch_threads_destroy (notmuch_threads_t *threads);
-/* Return an estimate of the number of messages matching a search
+/**
+ * Return an estimate of the number of messages matching a search.
*
* This function performs a search and returns Xapian's best
* guess as to number of matching messages.
*/
unsigned
notmuch_query_count_messages (notmuch_query_t *query);
-
-/* Return the number of threads matching a search.
+
+/**
+ * Return the number of threads matching a search.
*
* This function performs a search and returns the number of unique thread IDs
* in the matching messages. This is the same as number of threads matching a
unsigned
notmuch_query_count_threads (notmuch_query_t *query);
-/* Get the thread ID of 'thread'.
+/**
+ * Get the thread ID of 'thread'.
*
* The returned string belongs to 'thread' and as such, should not be
* modified by the caller and will only be valid for as long as the
const char *
notmuch_thread_get_thread_id (notmuch_thread_t *thread);
-/* Get the total number of messages in 'thread'.
+/**
+ * Get the total number of messages in 'thread'.
*
* This count consists of all messages in the database belonging to
* this thread. Contrast with notmuch_thread_get_matched_messages() .
int
notmuch_thread_get_total_messages (notmuch_thread_t *thread);
-/* Get a notmuch_messages_t iterator for the top-level messages in
+/**
+ * Get a notmuch_messages_t iterator for the top-level messages in
* 'thread' in oldest-first order.
*
* This iterator will not necessarily iterate over all of the messages
notmuch_messages_t *
notmuch_thread_get_toplevel_messages (notmuch_thread_t *thread);
-/* Get a notmuch_thread_t iterator for all messages in 'thread' in
+/**
+ * Get a notmuch_thread_t iterator for all messages in 'thread' in
* oldest-first order.
*
* The returned list will be destroyed when the thread is destroyed.
notmuch_messages_t *
notmuch_thread_get_messages (notmuch_thread_t *thread);
-/* Get the number of messages in 'thread' that matched the search.
+/**
+ * Get the number of messages in 'thread' that matched the search.
*
* This count includes only the messages in this thread that were
* matched by the search from which the thread was created and were
int
notmuch_thread_get_matched_messages (notmuch_thread_t *thread);
-/* Get the authors of 'thread' as a UTF-8 string.
+/**
+ * Get the authors of 'thread' as a UTF-8 string.
*
* The returned string is a comma-separated list of the names of the
* authors of mail messages in the query results that belong to this
const char *
notmuch_thread_get_authors (notmuch_thread_t *thread);
-/* Get the subject of 'thread' as a UTF-8 string.
+/**
+ * Get the subject of 'thread' as a UTF-8 string.
*
* The subject is taken from the first message (according to the query
* order---see notmuch_query_set_sort) in the query results that
const char *
notmuch_thread_get_subject (notmuch_thread_t *thread);
-/* Get the date of the oldest message in 'thread' as a time_t value.
+/**
+ * Get the date of the oldest message in 'thread' as a time_t value.
*/
time_t
notmuch_thread_get_oldest_date (notmuch_thread_t *thread);
-/* Get the date of the newest message in 'thread' as a time_t value.
+/**
+ * Get the date of the newest message in 'thread' as a time_t value.
*/
time_t
notmuch_thread_get_newest_date (notmuch_thread_t *thread);
-/* Get the tags for 'thread', returning a notmuch_tags_t object which
+/**
+ * Get the tags for 'thread', returning a notmuch_tags_t object which
* can be used to iterate over all tags.
*
* Note: In the Notmuch database, tags are stored on individual
*
* for (tags = notmuch_thread_get_tags (thread);
* notmuch_tags_valid (tags);
- * notmuch_result_move_to_next (tags))
+ * notmuch_tags_move_to_next (tags))
* {
* tag = notmuch_tags_get (tags);
* ....
notmuch_tags_t *
notmuch_thread_get_tags (notmuch_thread_t *thread);
-/* Destroy a notmuch_thread_t object. */
+/**
+ * Destroy a notmuch_thread_t object.
+ */
void
notmuch_thread_destroy (notmuch_thread_t *thread);
-/* Is the given 'messages' iterator pointing at a valid message.
+/**
+ * Is the given 'messages' iterator pointing at a valid message.
*
* When this function returns TRUE, notmuch_messages_get will return a
* valid object. Whereas when this function returns FALSE,
notmuch_bool_t
notmuch_messages_valid (notmuch_messages_t *messages);
-/* Get the current message from 'messages' as a notmuch_message_t.
+/**
+ * Get the current message from 'messages' as a notmuch_message_t.
*
* Note: The returned message belongs to 'messages' and has a lifetime
* identical to it (and the query to which it belongs).
notmuch_message_t *
notmuch_messages_get (notmuch_messages_t *messages);
-/* Move the 'messages' iterator to the next message.
+/**
+ * Move the 'messages' iterator to the next message.
*
* If 'messages' is already pointing at the last message then the
* iterator will be moved to a point just beyond that last message,
void
notmuch_messages_move_to_next (notmuch_messages_t *messages);
-/* Destroy a notmuch_messages_t object.
+/**
+ * Destroy a notmuch_messages_t object.
*
* It's not strictly necessary to call this function. All memory from
* the notmuch_messages_t object will be reclaimed when the containing
void
notmuch_messages_destroy (notmuch_messages_t *messages);
-/* Return a list of tags from all messages.
+/**
+ * Return a list of tags from all messages.
*
* The resulting list is guaranteed not to contain duplicated tags.
*
notmuch_tags_t *
notmuch_messages_collect_tags (notmuch_messages_t *messages);
-/* Get the message ID of 'message'.
+/**
+ * Get the message ID of 'message'.
*
* The returned string belongs to 'message' and as such, should not be
* modified by the caller and will only be valid for as long as the
const char *
notmuch_message_get_message_id (notmuch_message_t *message);
-/* Get the thread ID of 'message'.
+/**
+ * Get the thread ID of 'message'.
*
* The returned string belongs to 'message' and as such, should not be
* modified by the caller and will only be valid for as long as the
const char *
notmuch_message_get_thread_id (notmuch_message_t *message);
-/* Get a notmuch_messages_t iterator for all of the replies to
+/**
+ * Get a notmuch_messages_t iterator for all of the replies to
* 'message'.
*
* Note: This call only makes sense if 'message' was ultimately
notmuch_messages_t *
notmuch_message_get_replies (notmuch_message_t *message);
-/* Get a filename for the email corresponding to 'message'.
+/**
+ * Get a filename for the email corresponding to 'message'.
*
* The returned filename is an absolute filename, (the initial
* component will match notmuch_database_get_path() ).
const char *
notmuch_message_get_filename (notmuch_message_t *message);
-/* Get all filenames for the email corresponding to 'message'.
+/**
+ * Get all filenames for the email corresponding to 'message'.
*
* Returns a notmuch_filenames_t iterator listing all the filenames
* associated with 'message'. These files may not have identical
notmuch_filenames_t *
notmuch_message_get_filenames (notmuch_message_t *message);
-/* Message flags */
+/**
+ * Message flags.
+ */
typedef enum _notmuch_message_flag {
NOTMUCH_MESSAGE_FLAG_MATCH,
NOTMUCH_MESSAGE_FLAG_EXCLUDED
} notmuch_message_flag_t;
-/* Get a value of a flag for the email corresponding to 'message'. */
+/**
+ * Get a value of a flag for the email corresponding to 'message'.
+ */
notmuch_bool_t
notmuch_message_get_flag (notmuch_message_t *message,
notmuch_message_flag_t flag);
-/* Set a value of a flag for the email corresponding to 'message'. */
+/**
+ * Set a value of a flag for the email corresponding to 'message'.
+ */
void
notmuch_message_set_flag (notmuch_message_t *message,
notmuch_message_flag_t flag, notmuch_bool_t value);
-/* Get the date of 'message' as a time_t value.
+/**
+ * Get the date of 'message' as a time_t value.
*
* For the original textual representation of the Date header from the
* message call notmuch_message_get_header() with a header value of
- * "date". */
+ * "date".
+ */
time_t
notmuch_message_get_date (notmuch_message_t *message);
-/* Get the value of the specified header from 'message' as a UTF-8 string.
+/**
+ * Get the value of the specified header from 'message' as a UTF-8 string.
*
* Common headers are stored in the database when the message is
* indexed and will be returned from the database. Other headers will
const char *
notmuch_message_get_header (notmuch_message_t *message, const char *header);
-/* Get the tags for 'message', returning a notmuch_tags_t object which
+/**
+ * Get the tags for 'message', returning a notmuch_tags_t object which
* can be used to iterate over all tags.
*
* The tags object is owned by the message and as such, will only be
*
* for (tags = notmuch_message_get_tags (message);
* notmuch_tags_valid (tags);
- * notmuch_result_move_to_next (tags))
+ * notmuch_tags_move_to_next (tags))
* {
* tag = notmuch_tags_get (tags);
* ....
notmuch_tags_t *
notmuch_message_get_tags (notmuch_message_t *message);
-/* The longest possible tag value. */
+/**
+ * The longest possible tag value.
+ */
#define NOTMUCH_TAG_MAX 200
-/* Add a tag to the given message.
+/**
+ * Add a tag to the given message.
*
* Return value:
*
notmuch_status_t
notmuch_message_add_tag (notmuch_message_t *message, const char *tag);
-/* Remove a tag from the given message.
+/**
+ * Remove a tag from the given message.
*
* Return value:
*
notmuch_status_t
notmuch_message_remove_tag (notmuch_message_t *message, const char *tag);
-/* Remove all tags from the given message.
+/**
+ * Remove all tags from the given message.
*
* See notmuch_message_freeze for an example showing how to safely
* replace tag values.
notmuch_status_t
notmuch_message_remove_all_tags (notmuch_message_t *message);
-/* Add/remove tags according to maildir flags in the message filename(s)
+/**
+ * Add/remove tags according to maildir flags in the message filename(s).
*
* This function examines the filenames of 'message' for maildir
* flags, and adds or removes tags on 'message' as follows when these
notmuch_status_t
notmuch_message_maildir_flags_to_tags (notmuch_message_t *message);
-/* Rename message filename(s) to encode tags as maildir flags
+/**
+ * Rename message filename(s) to encode tags as maildir flags.
*
* Specifically, for each filename corresponding to this message:
*
notmuch_status_t
notmuch_message_tags_to_maildir_flags (notmuch_message_t *message);
-/* Freeze the current state of 'message' within the database.
+/**
+ * Freeze the current state of 'message' within the database.
*
* This means that changes to the message state, (via
* notmuch_message_add_tag, notmuch_message_remove_tag, and
notmuch_status_t
notmuch_message_freeze (notmuch_message_t *message);
-/* Thaw the current 'message', synchronizing any changes that may have
+/**
+ * Thaw the current 'message', synchronizing any changes that may have
* occurred while 'message' was frozen into the notmuch database.
*
* See notmuch_message_freeze for an example of how to use this
notmuch_status_t
notmuch_message_thaw (notmuch_message_t *message);
-/* Destroy a notmuch_message_t object.
+/**
+ * Destroy a notmuch_message_t object.
*
* It can be useful to call this function in the case of a single
* query object with many messages in the result, (such as iterating
void
notmuch_message_destroy (notmuch_message_t *message);
-/* Is the given 'tags' iterator pointing at a valid tag.
+/**
+ * Is the given 'tags' iterator pointing at a valid tag.
*
* When this function returns TRUE, notmuch_tags_get will return a
* valid string. Whereas when this function returns FALSE,
notmuch_bool_t
notmuch_tags_valid (notmuch_tags_t *tags);
-/* Get the current tag from 'tags' as a string.
+/**
+ * Get the current tag from 'tags' as a string.
*
* Note: The returned string belongs to 'tags' and has a lifetime
* identical to it (and the query to which it ultimately belongs).
const char *
notmuch_tags_get (notmuch_tags_t *tags);
-/* Move the 'tags' iterator to the next tag.
+/**
+ * Move the 'tags' iterator to the next tag.
*
* If 'tags' is already pointing at the last tag then the iterator
* will be moved to a point just beyond that last tag, (where
void
notmuch_tags_move_to_next (notmuch_tags_t *tags);
-/* Destroy a notmuch_tags_t object.
+/**
+ * Destroy a notmuch_tags_t object.
*
* It's not strictly necessary to call this function. All memory from
* the notmuch_tags_t object will be reclaimed when the containing
void
notmuch_tags_destroy (notmuch_tags_t *tags);
-/* Store an mtime within the database for 'directory'.
+/**
+ * Store an mtime within the database for 'directory'.
*
* The 'directory' should be an object retrieved from the database
* with notmuch_database_get_directory for a particular path.
notmuch_directory_set_mtime (notmuch_directory_t *directory,
time_t mtime);
-/* Get the mtime of a directory, (as previously stored with
+/**
+ * Get the mtime of a directory, (as previously stored with
* notmuch_directory_set_mtime).
*
* Returns 0 if no mtime has previously been stored for this
- * directory.*/
+ * directory.
+ */
time_t
notmuch_directory_get_mtime (notmuch_directory_t *directory);
-/* Get a notmuch_filenames_t iterator listing all the filenames of
+/**
+ * Get a notmuch_filenames_t iterator listing all the filenames of
* messages in the database within the given directory.
*
* The returned filenames will be the basename-entries only (not
- * complete paths). */
+ * complete paths).
+ */
notmuch_filenames_t *
notmuch_directory_get_child_files (notmuch_directory_t *directory);
-/* Get a notmuch_filenams_t iterator listing all the filenames of
+/**
+ * Get a notmuch_filenams_t iterator listing all the filenames of
* sub-directories in the database within the given directory.
*
* The returned filenames will be the basename-entries only (not
- * complete paths). */
+ * complete paths).
+ */
notmuch_filenames_t *
notmuch_directory_get_child_directories (notmuch_directory_t *directory);
-/* Destroy a notmuch_directory_t object. */
+/**
+ * Destroy a notmuch_directory_t object.
+ */
void
notmuch_directory_destroy (notmuch_directory_t *directory);
-/* Is the given 'filenames' iterator pointing at a valid filename.
+/**
+ * Is the given 'filenames' iterator pointing at a valid filename.
*
* When this function returns TRUE, notmuch_filenames_get will return
* a valid string. Whereas when this function returns FALSE,
notmuch_bool_t
notmuch_filenames_valid (notmuch_filenames_t *filenames);
-/* Get the current filename from 'filenames' as a string.
+/**
+ * Get the current filename from 'filenames' as a string.
*
* Note: The returned string belongs to 'filenames' and has a lifetime
* identical to it (and the directory to which it ultimately belongs).
const char *
notmuch_filenames_get (notmuch_filenames_t *filenames);
-/* Move the 'filenames' iterator to the next filename.
+/**
+ * Move the 'filenames' iterator to the next filename.
*
* If 'filenames' is already pointing at the last filename then the
* iterator will be moved to a point just beyond that last filename,
void
notmuch_filenames_move_to_next (notmuch_filenames_t *filenames);
-/* Destroy a notmuch_filenames_t object.
+/**
+ * Destroy a notmuch_filenames_t object.
*
* It's not strictly necessary to call this function. All memory from
* the notmuch_filenames_t object will be reclaimed when the
void
notmuch_filenames_destroy (notmuch_filenames_t *filenames);
+/* @} */
+
NOTMUCH_END_DECLS
#endif
{
unsigned int doc_id;
+ if (! threads)
+ return FALSE;
+
while (threads->doc_id_pos < threads->doc_ids->len) {
doc_id = g_array_index (threads->doc_ids, unsigned int,
threads->doc_id_pos);
_resolve_thread_relationships (thread);
/* Commit to returning thread. */
- talloc_steal (ctx, thread);
+ (void) talloc_steal (ctx, thread);
DONE:
talloc_free (local);
Notmuch restore supports two plain text dump formats, both with one message-id
per line, followed by a list of tags.
+.RS 4
+.TP 4
+.B batch-tag
+
+The default
+.B batch-tag
+dump format is intended to more robust against malformed message-ids
+and tags containing whitespace or non-\fBascii\fR(7) characters.
+Each line has the form
+
+.RS 4
+.RI "+<" "encoded-tag" "> " "" "+<" "encoded-tag" "> ... -- " "" " id:<" quoted-message-id >
+
+Tags are hex-encoded by replacing every byte not matching the regex
+.B [A-Za-z0-9@=.,_+-]
+with
+.B %nn
+where nn is the two digit hex encoding. The message ID is a valid Xapian
+query, quoted using Xapian boolean term quoting rules: if the ID contains
+whitespace or a close paren or starts with a double quote, it must be
+enclosed in double quotes and double quotes inside the ID must be doubled.
+The astute reader will notice this is a special case of the batch input
+format for \fBnotmuch-tag\fR(1); note that the single message-id query is
+mandatory for \fBnotmuch-restore\fR(1).
+
+.RE
+.RE
+
.RS 4
.TP 4
.B sup
.RE
-.RE
-.RS 4
-.TP 4
-.B batch-tag
-
-The
-.B batch-tag
-dump format is intended to more robust against malformed message-ids
-and tags containing whitespace or non-\fBascii\fR(7) characters.
-Each line has the form
-
-.RS 4
-.RI "+<" "encoded-tag" "> " "" "+<" "encoded-tag" "> ... -- " "" " id:<" quoted-message-id >
-
-Tags are hex-encoded by replacing every byte not matching the regex
-.B [A-Za-z0-9@=.,_+-]
-with
-.B %nn
-where nn is the two digit hex encoding. The message ID is a valid Xapian
-query, quoted using Xapian boolean term quoting rules: if the ID contains
-whitespace or a close paren or starts with a double quote, it must be
-enclosed in double quotes and double quotes inside the ID must be doubled.
-The astute reader will notice this is a special case of the batch input
-format for \fBnotmuch-tag\fR(1); note that the single message-id query is
-mandatory for \fBnotmuch-restore\fR(1).
-
.RE
Prevents hooks from being run.
.RE
+.RS 4
+.TP 4
+.BR \-\-quiet
+Do not print progress or results.
+.RE
.RE
.SH SEE ALSO
const char *path = notmuch_config_get_database_path (config);
const char *backup_path = NULL;
notmuch_status_t ret;
- notmuch_bool_t quiet;
+ notmuch_bool_t quiet = FALSE;
int opt_index;
notmuch_opt_desc_t options[] = {
opt_index = parse_arguments (argc, argv, options, 1);
if (opt_index < 0)
- return 1;
+ return EXIT_FAILURE;
if (! quiet)
printf ("Compacting database...\n");
quiet ? NULL : status_update_cb, NULL);
if (ret) {
fprintf (stderr, "Compaction failed: %s\n", notmuch_status_to_string (ret));
- return 1;
+ return EXIT_FAILURE;
}
if (! quiet) {
printf ("Done.\n");
}
- return 0;
+ return EXIT_SUCCESS;
}
return config->is_new;
}
+static const char *
+_config_get (notmuch_config_t *config, char **field,
+ const char *group, const char *key)
+{
+ /* read from config file and cache value, if not cached already */
+ if (*field == NULL) {
+ char *value;
+ value = g_key_file_get_string (config->key_file, group, key, NULL);
+ if (value) {
+ *field = talloc_strdup (config, value);
+ free (value);
+ }
+ }
+ return *field;
+}
+
+static void
+_config_set (notmuch_config_t *config, char **field,
+ const char *group, const char *key, const char *value)
+{
+ g_key_file_set_string (config->key_file, group, key, value);
+
+ /* drop the cached value */
+ talloc_free (*field);
+ *field = NULL;
+}
static const char **
_config_get_list (notmuch_config_t *config,
{
assert(outlist);
+ /* read from config file and cache value, if not cached already */
if (*outlist == NULL) {
char **inlist = g_key_file_get_string_list (config->key_file,
size_t length, const char ***config_var )
{
g_key_file_set_string_list (config->key_file, group, name, list, length);
+
+ /* drop the cached value */
talloc_free (*config_var);
*config_var = NULL;
}
const char *
notmuch_config_get_database_path (notmuch_config_t *config)
{
- char *path;
-
- if (config->database_path == NULL) {
- path = g_key_file_get_string (config->key_file,
- "database", "path", NULL);
- if (path) {
- config->database_path = talloc_strdup (config, path);
- free (path);
- }
- }
-
- return config->database_path;
+ return _config_get (config, &config->database_path, "database", "path");
}
void
notmuch_config_set_database_path (notmuch_config_t *config,
const char *database_path)
{
- g_key_file_set_string (config->key_file,
- "database", "path", database_path);
-
- talloc_free (config->database_path);
- config->database_path = NULL;
+ _config_set (config, &config->database_path, "database", "path", database_path);
}
const char *
notmuch_config_get_user_name (notmuch_config_t *config)
{
- char *name;
-
- if (config->user_name == NULL) {
- name = g_key_file_get_string (config->key_file,
- "user", "name", NULL);
- if (name) {
- config->user_name = talloc_strdup (config, name);
- free (name);
- }
- }
-
- return config->user_name;
+ return _config_get (config, &config->user_name, "user", "name");
}
void
notmuch_config_set_user_name (notmuch_config_t *config,
const char *user_name)
{
- g_key_file_set_string (config->key_file,
- "user", "name", user_name);
-
- talloc_free (config->user_name);
- config->user_name = NULL;
+ _config_set (config, &config->user_name, "user", "name", user_name);
}
const char *
notmuch_config_get_user_primary_email (notmuch_config_t *config)
{
- char *email;
-
- if (config->user_primary_email == NULL) {
- email = g_key_file_get_string (config->key_file,
- "user", "primary_email", NULL);
- if (email) {
- config->user_primary_email = talloc_strdup (config, email);
- free (email);
- }
- }
-
- return config->user_primary_email;
+ return _config_get (config, &config->user_primary_email, "user", "primary_email");
}
void
notmuch_config_set_user_primary_email (notmuch_config_t *config,
const char *primary_email)
{
- g_key_file_set_string (config->key_file,
- "user", "primary_email", primary_email);
-
- talloc_free (config->user_primary_email);
- config->user_primary_email = NULL;
+ _config_set (config, &config->user_primary_email, "user", "primary_email", primary_email);
}
const char **
int
notmuch_config_command (notmuch_config_t *config, int argc, char *argv[])
{
+ int ret;
+
argc--; argv++; /* skip subcommand argument */
if (argc < 1) {
fprintf (stderr, "Error: notmuch config requires at least one argument.\n");
- return 1;
+ return EXIT_FAILURE;
}
if (strcmp (argv[0], "get") == 0) {
if (argc != 2) {
fprintf (stderr, "Error: notmuch config get requires exactly "
"one argument.\n");
- return 1;
+ return EXIT_FAILURE;
}
- return notmuch_config_command_get (config, argv[1]);
+ ret = notmuch_config_command_get (config, argv[1]);
} else if (strcmp (argv[0], "set") == 0) {
if (argc < 2) {
fprintf (stderr, "Error: notmuch config set requires at least "
"one argument.\n");
- return 1;
+ return EXIT_FAILURE;
}
- return notmuch_config_command_set (config, argv[1], argc - 2, argv + 2);
+ ret = notmuch_config_command_set (config, argv[1], argc - 2, argv + 2);
} else if (strcmp (argv[0], "list") == 0) {
- return notmuch_config_command_list (config);
+ ret = notmuch_config_command_list (config);
+ } else {
+ fprintf (stderr, "Unrecognized argument for notmuch config: %s\n",
+ argv[0]);
+ return EXIT_FAILURE;
}
- fprintf (stderr, "Unrecognized argument for notmuch config: %s\n",
- argv[0]);
- return 1;
+ return ret ? EXIT_FAILURE : EXIT_SUCCESS;
+
}
notmuch_bool_t
};
opt_index = parse_arguments (argc, argv, options, 1);
-
- if (opt_index < 0) {
- return 1;
- }
+ if (opt_index < 0)
+ return EXIT_FAILURE;
if (input_file_name) {
batch = TRUE;
if (input == NULL) {
fprintf (stderr, "Error opening %s for reading: %s\n",
input_file_name, strerror (errno));
- return 1;
+ return EXIT_FAILURE;
}
}
if (batch && opt_index != argc) {
fprintf (stderr, "--batch and query string are not compatible\n");
- return 1;
+ return EXIT_FAILURE;
}
if (notmuch_database_open (notmuch_config_get_database_path (config),
NOTMUCH_DATABASE_MODE_READ_ONLY, ¬much))
- return 1;
+ return EXIT_FAILURE;
query_str = query_string_from_args (config, argc-opt_index, argv+opt_index);
if (query_str == NULL) {
fprintf (stderr, "Out of memory.\n");
- return 1;
+ return EXIT_FAILURE;
}
if (exclude == EXCLUDE_TRUE) {
if (input != stdin)
fclose (input);
- return ret;
+ return ret ? EXIT_FAILURE : EXIT_SUCCESS;
}
if (notmuch_database_open (notmuch_config_get_database_path (config),
NOTMUCH_DATABASE_MODE_READ_ONLY, ¬much))
- return 1;
+ return EXIT_FAILURE;
char *output_file_name = NULL;
int opt_index;
- int output_format = DUMP_FORMAT_SUP;
+ int output_format = DUMP_FORMAT_BATCH_TAG;
notmuch_opt_desc_t options[] = {
{ NOTMUCH_OPT_KEYWORD, &output_format, "format", 'f',
};
opt_index = parse_arguments (argc, argv, options, 1);
-
- if (opt_index < 0) {
- /* diagnostics already printed */
- return 1;
- }
+ if (opt_index < 0)
+ return EXIT_FAILURE;
if (output_file_name) {
output = fopen (output_file_name, "w");
if (output == NULL) {
fprintf (stderr, "Error opening %s for writing: %s\n",
output_file_name, strerror (errno));
- return 1;
+ return EXIT_FAILURE;
}
}
query_str = query_string_from_args (notmuch, argc - opt_index, argv + opt_index);
if (query_str == NULL) {
fprintf (stderr, "Out of memory.\n");
- return 1;
+ return EXIT_FAILURE;
}
}
query = notmuch_query_create (notmuch, query_str);
if (query == NULL) {
fprintf (stderr, "Out of memory\n");
- return 1;
+ return EXIT_FAILURE;
}
/* Don't ask xapian to sort by Message-ID. Xapian optimizes returning the
* first results quickly at the expense of total time.
&buffer, &buffer_size) != HEX_SUCCESS) {
fprintf (stderr, "Error: failed to hex-encode tag %s\n",
tag_str);
- return 1;
+ return EXIT_FAILURE;
}
fprintf (output, "+%s", buffer);
}
&buffer, &buffer_size)) {
fprintf (stderr, "Error quoting message id %s: %s\n",
message_id, strerror (errno));
- return 1;
+ return EXIT_FAILURE;
}
fprintf (output, " -- %s\n", buffer);
}
notmuch_query_destroy (query);
notmuch_database_destroy (notmuch);
- return 0;
+ return EXIT_SUCCESS;
}
* The file is renamed to encode notmuch tags as maildir flags. */
static void
add_file_to_database (notmuch_database_t *notmuch, const char *path,
- tag_op_list_t *tag_ops)
+ tag_op_list_t *tag_ops, notmuch_bool_t synchronize_flags)
{
notmuch_message_t *message;
notmuch_status_t status;
if (status == NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID) {
/* Don't change tags of an existing message. */
- status = notmuch_message_tags_to_maildir_flags (message);
- if (status != NOTMUCH_STATUS_SUCCESS)
- fprintf (stderr, "Error: failed to sync tags to maildir flags\n");
+ if (synchronize_flags) {
+ status = notmuch_message_tags_to_maildir_flags (message);
+ if (status != NOTMUCH_STATUS_SUCCESS)
+ fprintf (stderr, "Error: failed to sync tags to maildir flags\n");
+ }
} else {
- tag_op_list_apply (message, tag_ops, TAG_FLAG_MAILDIR_SYNC);
+ tag_op_flag_t flags = synchronize_flags ? TAG_FLAG_MAILDIR_SYNC : 0;
+
+ tag_op_list_apply (message, tag_ops, flags);
}
notmuch_message_destroy (message);
static notmuch_bool_t
insert_message (void *ctx, notmuch_database_t *notmuch, int fdin,
- const char *dir, tag_op_list_t *tag_ops)
+ const char *dir, tag_op_list_t *tag_ops,
+ notmuch_bool_t synchronize_flags)
{
char *tmppath;
char *newpath;
/* Even if adding the message to the notmuch database fails,
* the message is on disk and we consider the delivery completed. */
- add_file_to_database (notmuch, newpath, tag_ops);
+ add_file_to_database (notmuch, newpath, tag_ops, synchronize_flags);
return TRUE;
char *query_string = NULL;
const char *folder = NULL;
notmuch_bool_t create_folder = FALSE;
+ notmuch_bool_t synchronize_flags;
const char *maildir;
int opt_index;
unsigned int i;
};
opt_index = parse_arguments (argc, argv, options, 1);
-
- if (opt_index < 0) {
- /* diagnostics already printed */
- return 1;
- }
+ if (opt_index < 0)
+ return EXIT_FAILURE;
db_path = notmuch_config_get_database_path (config);
new_tags = notmuch_config_get_new_tags (config, &new_tags_length);
+ synchronize_flags = notmuch_config_get_maildir_synchronize_flags (config);
tag_ops = tag_op_list_create (config);
if (tag_ops == NULL) {
fprintf (stderr, "Out of memory.\n");
- return 1;
+ return EXIT_FAILURE;
}
for (i = 0; i < new_tags_length; i++) {
if (tag_op_list_append (tag_ops, new_tags[i], FALSE))
- return 1;
+ return EXIT_FAILURE;
}
if (parse_tag_command_line (config, argc - opt_index, argv + opt_index,
&query_string, tag_ops))
- return 1;
+ return EXIT_FAILURE;
if (*query_string != '\0') {
fprintf (stderr, "Error: unexpected query string: %s\n", query_string);
- return 1;
+ return EXIT_FAILURE;
}
if (folder == NULL) {
} else {
if (! check_folder_name (folder)) {
fprintf (stderr, "Error: bad folder name: %s\n", folder);
- return 1;
+ return EXIT_FAILURE;
}
maildir = talloc_asprintf (config, "%s/%s", db_path, folder);
if (! maildir) {
fprintf (stderr, "Out of memory\n");
- return 1;
+ return EXIT_FAILURE;
}
if (create_folder && ! maildir_create_folder (config, maildir)) {
fprintf (stderr, "Error: creating maildir %s: %s\n",
maildir, strerror (errno));
- return 1;
+ return EXIT_FAILURE;
}
}
if (notmuch_database_open (notmuch_config_get_database_path (config),
NOTMUCH_DATABASE_MODE_READ_WRITE, ¬much))
- return 1;
+ return EXIT_FAILURE;
- ret = insert_message (config, notmuch, STDIN_FILENO, maildir, tag_ops);
+ ret = insert_message (config, notmuch, STDIN_FILENO, maildir, tag_ops,
+ synchronize_flags);
notmuch_database_destroy (notmuch);
- return (ret) ? 0 : 1;
+ return ret ? EXIT_SUCCESS : EXIT_FAILURE;
}
_filename_node_t **tail;
} _filename_list_t;
+enum verbosity {
+ VERBOSITY_QUIET,
+ VERBOSITY_NORMAL,
+ VERBOSITY_VERBOSE,
+};
+
typedef struct {
int output_is_a_tty;
- notmuch_bool_t verbose;
+ enum verbosity verbosity;
notmuch_bool_t debug;
const char **new_tags;
size_t new_tags_length;
char *abspath;
int err, saved_errno;
-#ifdef _DIRENT_HAVE_D_TYPE
+#if HAVE_D_TYPE
/* Mapping from d_type to stat mode_t. We omit DT_LNK so that
* we'll fall through to stat and get the real file type. */
static const mode_t modes[] = {
return FALSE;
}
+/* Add a single file to the database. */
+static notmuch_status_t
+add_file (notmuch_database_t *notmuch, const char *filename,
+ add_files_state_t *state)
+{
+ notmuch_message_t *message = NULL;
+ const char **tag;
+ notmuch_status_t status;
+
+ status = notmuch_database_begin_atomic (notmuch);
+ if (status)
+ goto DONE;
+
+ status = notmuch_database_add_message (notmuch, filename, &message);
+ switch (status) {
+ /* Success. */
+ case NOTMUCH_STATUS_SUCCESS:
+ state->added_messages++;
+ notmuch_message_freeze (message);
+ for (tag = state->new_tags; *tag != NULL; tag++)
+ notmuch_message_add_tag (message, *tag);
+ if (state->synchronize_flags)
+ notmuch_message_maildir_flags_to_tags (message);
+ notmuch_message_thaw (message);
+ break;
+ /* Non-fatal issues (go on to next file). */
+ case NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID:
+ if (state->synchronize_flags)
+ notmuch_message_maildir_flags_to_tags (message);
+ break;
+ case NOTMUCH_STATUS_FILE_NOT_EMAIL:
+ fprintf (stderr, "Note: Ignoring non-mail file: %s\n", filename);
+ break;
+ /* Fatal issues. Don't process anymore. */
+ case NOTMUCH_STATUS_READ_ONLY_DATABASE:
+ case NOTMUCH_STATUS_XAPIAN_EXCEPTION:
+ case NOTMUCH_STATUS_OUT_OF_MEMORY:
+ fprintf (stderr, "Error: %s. Halting processing.\n",
+ notmuch_status_to_string (status));
+ goto DONE;
+ default:
+ INTERNAL_ERROR ("add_message returned unexpected value: %d", status);
+ goto DONE;
+ }
+
+ status = notmuch_database_end_atomic (notmuch);
+
+ DONE:
+ if (message)
+ notmuch_message_destroy (message);
+
+ return status;
+}
+
/* Examine 'path' recursively as follows:
*
* o Ask the filesystem for the mtime of 'path' (fs_mtime)
char *next = NULL;
time_t fs_mtime, db_mtime;
notmuch_status_t status, ret = NOTMUCH_STATUS_SUCCESS;
- notmuch_message_t *message = NULL;
struct dirent **fs_entries = NULL;
int i, num_fs_entries = 0, entry_type;
notmuch_directory_t *directory;
time_t stat_time;
struct stat st;
notmuch_bool_t is_maildir;
- const char **tag;
if (stat (path, &st)) {
fprintf (stderr, "Error reading directory %s: %s\n",
state->processed_files++;
- if (state->verbose) {
+ if (state->verbosity >= VERBOSITY_VERBOSE) {
if (state->output_is_a_tty)
printf("\r\033[K");
- printf ("%i/%i: %s",
- state->processed_files,
- state->total_files,
+ printf ("%i/%i: %s", state->processed_files, state->total_files,
next);
putchar((state->output_is_a_tty) ? '\r' : '\n');
fflush (stdout);
}
- status = notmuch_database_begin_atomic (notmuch);
+ status = add_file (notmuch, next, state);
if (status) {
ret = status;
goto DONE;
}
- status = notmuch_database_add_message (notmuch, next, &message);
- switch (status) {
- /* success */
- case NOTMUCH_STATUS_SUCCESS:
- state->added_messages++;
- notmuch_message_freeze (message);
- for (tag=state->new_tags; *tag != NULL; tag++)
- notmuch_message_add_tag (message, *tag);
- if (state->synchronize_flags == TRUE)
- notmuch_message_maildir_flags_to_tags (message);
- notmuch_message_thaw (message);
- break;
- /* Non-fatal issues (go on to next file) */
- case NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID:
- if (state->synchronize_flags == TRUE)
- notmuch_message_maildir_flags_to_tags (message);
- break;
- case NOTMUCH_STATUS_FILE_NOT_EMAIL:
- fprintf (stderr, "Note: Ignoring non-mail file: %s\n",
- next);
- break;
- /* Fatal issues. Don't process anymore. */
- case NOTMUCH_STATUS_READ_ONLY_DATABASE:
- case NOTMUCH_STATUS_XAPIAN_EXCEPTION:
- case NOTMUCH_STATUS_OUT_OF_MEMORY:
- fprintf (stderr, "Error: %s. Halting processing.\n",
- notmuch_status_to_string (status));
- ret = status;
- goto DONE;
- default:
- case NOTMUCH_STATUS_FILE_ERROR:
- case NOTMUCH_STATUS_NULL_POINTER:
- case NOTMUCH_STATUS_TAG_TOO_LONG:
- case NOTMUCH_STATUS_UNBALANCED_FREEZE_THAW:
- case NOTMUCH_STATUS_UNBALANCED_ATOMIC:
- case NOTMUCH_STATUS_LAST_STATUS:
- INTERNAL_ERROR ("add_message returned unexpected value: %d", status);
- goto DONE;
- }
-
- status = notmuch_database_end_atomic (notmuch);
- if (status) {
- ret = status;
- goto DONE;
- }
-
- if (message) {
- notmuch_message_destroy (message);
- message = NULL;
- }
-
if (do_print_progress) {
do_print_progress = 0;
generic_print_progress ("Processed", "files", state->tv_start,
{
struct dirent *entry = NULL;
char *next;
- struct stat st;
struct dirent **fs_entries = NULL;
int num_fs_entries = scandir (path, &fs_entries, 0, dirent_sort_inode);
- int i = 0;
+ int entry_type, i;
if (num_fs_entries == -1) {
fprintf (stderr, "Warning: failed to open directory %s: %s\n",
goto DONE;
}
- while (!interrupted) {
- if (i == num_fs_entries)
- break;
-
- entry = fs_entries[i++];
+ for (i = 0; i < num_fs_entries && ! interrupted; i++) {
+ entry = fs_entries[i];
/* Ignore special directories to avoid infinite recursion.
* Also ignore the .notmuch directory and files/directories
strcmp (entry->d_name, ".notmuch") == 0 ||
_entry_in_ignore_list (entry->d_name, state))
{
- if (_entry_in_ignore_list (entry->d_name, state) && state->debug)
+ if (state->debug && _entry_in_ignore_list (entry->d_name, state))
printf ("(D) count_files: explicitly ignoring %s/%s\n",
path,
entry->d_name);
continue;
}
- stat (next, &st);
-
- if (S_ISREG (st.st_mode)) {
+ entry_type = dirent_type (path, entry);
+ if (entry_type == S_IFREG) {
*count = *count + 1;
- if (*count % 1000 == 0) {
+ if (*count % 1000 == 0 && state->verbosity >= VERBOSITY_NORMAL) {
printf ("Found %d files so far.\r", *count);
fflush (stdout);
}
- } else if (S_ISDIR (st.st_mode)) {
+ } else if (entry_type == S_IFDIR) {
count_files (next, count, state);
}
return status;
}
+static void
+print_results (const add_files_state_t *state)
+{
+ double elapsed;
+ struct timeval tv_now;
+
+ gettimeofday (&tv_now, NULL);
+ elapsed = notmuch_time_elapsed (state->tv_start, tv_now);
+
+ if (state->processed_files) {
+ printf ("Processed %d %s in ", state->processed_files,
+ state->processed_files == 1 ? "file" : "total files");
+ notmuch_time_print_formatted_seconds (elapsed);
+ if (elapsed > 1)
+ printf (" (%d files/sec.).\033[K\n",
+ (int) (state->processed_files / elapsed));
+ else
+ printf (".\033[K\n");
+ }
+
+ if (state->added_messages)
+ printf ("Added %d new %s to the database.", state->added_messages,
+ state->added_messages == 1 ? "message" : "messages");
+ else
+ printf ("No new mail.");
+
+ if (state->removed_messages)
+ printf (" Removed %d %s.", state->removed_messages,
+ state->removed_messages == 1 ? "message" : "messages");
+
+ if (state->renamed_messages)
+ printf (" Detected %d file %s.", state->renamed_messages,
+ state->renamed_messages == 1 ? "rename" : "renames");
+
+ printf ("\n");
+}
+
int
notmuch_new_command (notmuch_config_t *config, int argc, char *argv[])
{
notmuch_database_t *notmuch;
add_files_state_t add_files_state;
- double elapsed;
- struct timeval tv_now, tv_start;
+ struct timeval tv_start;
int ret = 0;
struct stat st;
const char *db_path;
int i;
notmuch_bool_t timer_is_active = FALSE;
notmuch_bool_t no_hooks = FALSE;
+ notmuch_bool_t quiet = FALSE, verbose = FALSE;
- add_files_state.verbose = FALSE;
+ add_files_state.verbosity = VERBOSITY_NORMAL;
add_files_state.debug = FALSE;
add_files_state.output_is_a_tty = isatty (fileno (stdout));
notmuch_opt_desc_t options[] = {
- { NOTMUCH_OPT_BOOLEAN, &add_files_state.verbose, "verbose", 'v', 0 },
+ { NOTMUCH_OPT_BOOLEAN, &quiet, "quiet", 'q', 0 },
+ { NOTMUCH_OPT_BOOLEAN, &verbose, "verbose", 'v', 0 },
{ NOTMUCH_OPT_BOOLEAN, &add_files_state.debug, "debug", 'd', 0 },
{ NOTMUCH_OPT_BOOLEAN, &no_hooks, "no-hooks", 'n', 0 },
{ 0, 0, 0, 0, 0 }
};
opt_index = parse_arguments (argc, argv, options, 1);
- if (opt_index < 0) {
- /* diagnostics already printed */
- return 1;
- }
+ if (opt_index < 0)
+ return EXIT_FAILURE;
+
+ /* quiet trumps verbose */
+ if (quiet)
+ add_files_state.verbosity = VERBOSITY_QUIET;
+ else if (verbose)
+ add_files_state.verbosity = VERBOSITY_VERBOSE;
add_files_state.new_tags = notmuch_config_get_new_tags (config, &add_files_state.new_tags_length);
add_files_state.new_ignore = notmuch_config_get_new_ignore (config, &add_files_state.new_ignore_length);
if (!no_hooks) {
ret = notmuch_run_hook (db_path, "pre-new");
if (ret)
- return ret;
+ return EXIT_FAILURE;
}
dot_notmuch_path = talloc_asprintf (config, "%s/%s", db_path, ".notmuch");
count = 0;
count_files (db_path, &count, &add_files_state);
if (interrupted)
- return 1;
+ return EXIT_FAILURE;
- printf ("Found %d total files (that's not much mail).\n", count);
+ if (add_files_state.verbosity >= VERBOSITY_NORMAL)
+ printf ("Found %d total files (that's not much mail).\n", count);
if (notmuch_database_create (db_path, ¬much))
- return 1;
+ return EXIT_FAILURE;
add_files_state.total_files = count;
} else {
if (notmuch_database_open (db_path, NOTMUCH_DATABASE_MODE_READ_WRITE,
¬much))
- return 1;
+ return EXIT_FAILURE;
if (notmuch_database_needs_upgrade (notmuch)) {
- printf ("Welcome to a new version of notmuch! Your database will now be upgraded.\n");
+ if (add_files_state.verbosity >= VERBOSITY_NORMAL)
+ printf ("Welcome to a new version of notmuch! Your database will now be upgraded.\n");
gettimeofday (&add_files_state.tv_start, NULL);
- notmuch_database_upgrade (notmuch, upgrade_print_progress,
+ notmuch_database_upgrade (notmuch,
+ add_files_state.verbosity >= VERBOSITY_NORMAL ? upgrade_print_progress : NULL,
&add_files_state);
- printf ("Your notmuch database has now been upgraded to database format version %u.\n",
+ if (add_files_state.verbosity >= VERBOSITY_NORMAL)
+ printf ("Your notmuch database has now been upgraded to database format version %u.\n",
notmuch_database_get_version (notmuch));
}
}
if (notmuch == NULL)
- return 1;
+ return EXIT_FAILURE;
/* Setup our handler for SIGINT. We do this after having
* potentially done a database upgrade we this interrupt handler
add_files_state.removed_directories = _filename_list_create (config);
add_files_state.directory_mtimes = _filename_list_create (config);
- if (! debugger_is_active () && add_files_state.output_is_a_tty
- && ! add_files_state.verbose) {
+ if (add_files_state.verbosity == VERBOSITY_NORMAL &&
+ add_files_state.output_is_a_tty && ! debugger_is_active ()) {
setup_progress_printing_timer ();
timer_is_active = TRUE;
}
if (timer_is_active)
stop_progress_printing_timer ();
- gettimeofday (&tv_now, NULL);
- elapsed = notmuch_time_elapsed (add_files_state.tv_start,
- tv_now);
-
- if (add_files_state.processed_files) {
- printf ("Processed %d %s in ", add_files_state.processed_files,
- add_files_state.processed_files == 1 ?
- "file" : "total files");
- notmuch_time_print_formatted_seconds (elapsed);
- if (elapsed > 1) {
- printf (" (%d files/sec.).\033[K\n",
- (int) (add_files_state.processed_files / elapsed));
- } else {
- printf (".\033[K\n");
- }
- }
-
- if (add_files_state.added_messages) {
- printf ("Added %d new %s to the database.",
- add_files_state.added_messages,
- add_files_state.added_messages == 1 ?
- "message" : "messages");
- } else {
- printf ("No new mail.");
- }
-
- if (add_files_state.removed_messages) {
- printf (" Removed %d %s.",
- add_files_state.removed_messages,
- add_files_state.removed_messages == 1 ? "message" : "messages");
- }
-
- if (add_files_state.renamed_messages) {
- printf (" Detected %d file %s.",
- add_files_state.renamed_messages,
- add_files_state.renamed_messages == 1 ? "rename" : "renames");
- }
-
- printf ("\n");
+ if (add_files_state.verbosity >= VERBOSITY_NORMAL)
+ print_results (&add_files_state);
if (ret)
fprintf (stderr, "Note: A fatal error was encountered: %s\n",
if (!no_hooks && !ret && !interrupted)
ret = notmuch_run_hook (db_path, "post-new");
- return ret || interrupted;
+ return ret || interrupted ? EXIT_FAILURE : EXIT_SUCCESS;
}
notmuch_database_t *notmuch;
notmuch_query_t *query;
char *query_string;
- int opt_index, ret = 0;
+ int opt_index;
int (*reply_format_func) (void *ctx,
notmuch_config_t *config,
notmuch_query_t *query,
};
opt_index = parse_arguments (argc, argv, options, 1);
- if (opt_index < 0) {
- /* diagnostics already printed */
- return 1;
- }
+ if (opt_index < 0)
+ return EXIT_FAILURE;
if (format == FORMAT_HEADERS_ONLY) {
reply_format_func = notmuch_reply_format_headers_only;
query_string = query_string_from_args (config, argc-opt_index, argv+opt_index);
if (query_string == NULL) {
fprintf (stderr, "Out of memory\n");
- return 1;
+ return EXIT_FAILURE;
}
if (*query_string == '\0') {
fprintf (stderr, "Error: notmuch reply requires at least one search term.\n");
- return 1;
+ return EXIT_FAILURE;
}
if (notmuch_database_open (notmuch_config_get_database_path (config),
NOTMUCH_DATABASE_MODE_READ_ONLY, ¬much))
- return 1;
+ return EXIT_FAILURE;
query = notmuch_query_create (notmuch, query_string);
if (query == NULL) {
fprintf (stderr, "Out of memory\n");
- return 1;
+ return EXIT_FAILURE;
}
if (reply_format_func (config, config, query, ¶ms, reply_all, sp) != 0)
- return 1;
+ return EXIT_FAILURE;
notmuch_crypto_cleanup (¶ms.crypto);
notmuch_query_destroy (query);
notmuch_database_destroy (notmuch);
- return ret;
+ return EXIT_SUCCESS;
}
if (notmuch_database_open (notmuch_config_get_database_path (config),
NOTMUCH_DATABASE_MODE_READ_WRITE, ¬much))
- return 1;
+ return EXIT_FAILURE;
if (notmuch_config_get_maildir_synchronize_flags (config))
flags |= TAG_FLAG_MAILDIR_SYNC;
};
opt_index = parse_arguments (argc, argv, options, 1);
-
- if (opt_index < 0) {
- /* diagnostics already printed */
- return 1;
- }
+ if (opt_index < 0)
+ return EXIT_FAILURE;
if (! accumulate)
flags |= TAG_FLAG_REMOVE_ALL;
if (input == NULL) {
fprintf (stderr, "Error opening %s for reading: %s\n",
input_file_name, strerror (errno));
- return 1;
+ return EXIT_FAILURE;
}
}
if (opt_index < argc) {
- fprintf (stderr,
- "Unused positional parameter: %s\n",
- argv[opt_index]);
- return 1;
+ fprintf (stderr, "Unused positional parameter: %s\n", argv[opt_index]);
+ return EXIT_FAILURE;
}
tag_ops = tag_op_list_create (config);
if (tag_ops == NULL) {
fprintf (stderr, "Out of memory.\n");
- return 1;
+ return EXIT_FAILURE;
}
do {
/* empty input file not considered an error */
if (line_len < 0)
- return 0;
+ return EXIT_SUCCESS;
} while ((line_len == 0) ||
(line[0] == '#') ||
if (input != stdin)
fclose (input);
- return ret;
+ return ret ? EXIT_FAILURE : EXIT_SUCCESS;
}
};
opt_index = parse_arguments (argc, argv, options, 1);
-
- if (opt_index < 0) {
- return 1;
- }
+ if (opt_index < 0)
+ return EXIT_FAILURE;
switch (format_sel) {
case NOTMUCH_FORMAT_TEXT:
case NOTMUCH_FORMAT_TEXT0:
if (output == OUTPUT_SUMMARY) {
fprintf (stderr, "Error: --format=text0 is not compatible with --output=summary.\n");
- return 1;
+ return EXIT_FAILURE;
}
format = sprinter_text0_create (config, stdout);
break;
if (notmuch_database_open (notmuch_config_get_database_path (config),
NOTMUCH_DATABASE_MODE_READ_ONLY, ¬much))
- return 1;
+ return EXIT_FAILURE;
query_str = query_string_from_args (notmuch, argc-opt_index, argv+opt_index);
if (query_str == NULL) {
fprintf (stderr, "Out of memory.\n");
- return 1;
+ return EXIT_FAILURE;
}
if (*query_str == '\0') {
fprintf (stderr, "Error: notmuch search requires at least one search term.\n");
- return 1;
+ return EXIT_FAILURE;
}
query = notmuch_query_create (notmuch, query_str);
if (query == NULL) {
fprintf (stderr, "Out of memory\n");
- return 1;
+ return EXIT_FAILURE;
}
notmuch_query_set_sort (query, sort);
talloc_free (format);
- return ret;
+ return ret ? EXIT_FAILURE : EXIT_SUCCESS;
}
fflush (stdout); \
if (getline (&response, &response_size, stdin) < 0) { \
printf ("Exiting.\n"); \
- exit (1); \
+ exit (EXIT_FAILURE); \
} \
chomp_newline (response); \
} while (0)
g_ptr_array_free (tags, TRUE);
}
+ if (notmuch_config_save (config))
+ return EXIT_FAILURE;
- if (! notmuch_config_save (config)) {
- if (notmuch_config_is_new (config))
- welcome_message_post_setup ();
- return 0;
- } else {
- return 1;
- }
+ if (notmuch_config_is_new (config))
+ welcome_message_post_setup ();
+
+ return EXIT_SUCCESS;
}
notmuch_messages_t *messages;
notmuch_status_t status, res = NOTMUCH_STATUS_SUCCESS;
+ threads = notmuch_query_search_threads (query);
+ if (! threads)
+ return 1;
+
sp->begin_list (sp);
- for (threads = notmuch_query_search_threads (query);
+ for ( ;
notmuch_threads_valid (threads);
notmuch_threads_move_to_next (threads))
{
};
opt_index = parse_arguments (argc, argv, options, 1);
- if (opt_index < 0) {
- /* diagnostics already printed */
- return 1;
- }
+ if (opt_index < 0)
+ return EXIT_FAILURE;
/* decryption implies verification */
if (params.crypto.decrypt)
case NOTMUCH_FORMAT_MBOX:
if (params.part > 0) {
fprintf (stderr, "Error: specifying parts is incompatible with mbox output format.\n");
- return 1;
+ return EXIT_FAILURE;
}
format = &format_mbox;
query_string = query_string_from_args (config, argc-opt_index, argv+opt_index);
if (query_string == NULL) {
fprintf (stderr, "Out of memory\n");
- return 1;
+ return EXIT_FAILURE;
}
if (*query_string == '\0') {
fprintf (stderr, "Error: notmuch show requires at least one search term.\n");
- return 1;
+ return EXIT_FAILURE;
}
if (notmuch_database_open (notmuch_config_get_database_path (config),
NOTMUCH_DATABASE_MODE_READ_ONLY, ¬much))
- return 1;
+ return EXIT_FAILURE;
query = notmuch_query_create (notmuch, query_string);
if (query == NULL) {
fprintf (stderr, "Out of memory\n");
- return 1;
+ return EXIT_FAILURE;
}
/* Create structure printer. */
notmuch_query_destroy (query);
notmuch_database_destroy (notmuch);
- return ret;
+ return ret ? EXIT_FAILURE : EXIT_SUCCESS;
}
FILE *input = stdin;
char *input_file_name = NULL;
int opt_index;
- int ret = 0;
+ int ret;
/* Setup our handler for SIGINT */
memset (&action, 0, sizeof (struct sigaction));
opt_index = parse_arguments (argc, argv, options, 1);
if (opt_index < 0)
- return 1;
+ return EXIT_FAILURE;
if (input_file_name) {
batch = TRUE;
if (input == NULL) {
fprintf (stderr, "Error opening %s for reading: %s\n",
input_file_name, strerror (errno));
- return 1;
+ return EXIT_FAILURE;
}
}
if (batch) {
if (opt_index != argc) {
fprintf (stderr, "Can't specify both cmdline and stdin!\n");
- return 1;
+ return EXIT_FAILURE;
}
if (remove_all) {
fprintf (stderr, "Can't specify both --remove-all and --batch\n");
- return 1;
+ return EXIT_FAILURE;
}
} else {
tag_ops = tag_op_list_create (config);
if (tag_ops == NULL) {
fprintf (stderr, "Out of memory.\n");
- return 1;
+ return EXIT_FAILURE;
}
if (parse_tag_command_line (config, argc - opt_index, argv + opt_index,
&query_string, tag_ops))
- return 1;
+ return EXIT_FAILURE;
if (tag_op_list_size (tag_ops) == 0 && ! remove_all) {
fprintf (stderr, "Error: 'notmuch tag' requires at least one tag to add or remove.\n");
- return 1;
+ return EXIT_FAILURE;
}
if (*query_string == '\0') {
fprintf (stderr, "Error: notmuch tag requires at least one search term.\n");
- return 1;
+ return EXIT_FAILURE;
}
}
if (notmuch_database_open (notmuch_config_get_database_path (config),
NOTMUCH_DATABASE_MODE_READ_WRITE, ¬much))
- return 1;
+ return EXIT_FAILURE;
if (notmuch_config_get_maildir_synchronize_flags (config))
tag_flags |= TAG_FLAG_MAILDIR_SYNC;
if (input != stdin)
fclose (input);
- return ret || interrupted;
+ return ret || interrupted ? EXIT_FAILURE : EXIT_SUCCESS;
}
#include "notmuch-client.h"
+/*
+ * Notmuch subcommand hook.
+ *
+ * The return value will be used as notmuch exit status code,
+ * preferrably EXIT_SUCCESS or EXIT_FAILURE.
+ */
typedef int (*command_function_t) (notmuch_config_t *config, int argc, char *argv[]);
typedef struct command {
if (argc == 0) {
printf ("The notmuch mail system.\n\n");
usage (stdout);
- return 0;
+ return EXIT_SUCCESS;
}
if (strcmp (argv[0], "help") == 0) {
"\tof difficulties check that MANPATH includes the pages\n"
"\tinstalled by notmuch.\n\n"
"\tTry \"notmuch help\" for a list of topics.\n");
- return 0;
+ return EXIT_SUCCESS;
}
command = find_command (argv[0]);
fprintf (stderr,
"\nSorry, %s is not a known command. There's not much I can do to help.\n\n",
argv[0]);
- return 1;
+ return EXIT_FAILURE;
}
/* Handle the case of "notmuch" being invoked with no command
if (errno != ENOENT) {
fprintf (stderr, "Error looking for notmuch database at %s: %s\n",
db_path, strerror (errno));
- return 1;
+ return EXIT_FAILURE;
}
printf ("Notmuch is configured, but there's not yet a database at\n\n\t%s\n\n",
db_path);
"Note that the first run of \"notmuch new\" can take a very long time\n"
"and that the resulting database will use roughly the same amount of\n"
"storage space as the email being indexed.\n\n");
- return 0;
+ return EXIT_SUCCESS;
}
printf ("Notmuch is configured and appears to have a database. Excellent!\n\n"
notmuch_config_get_user_name (config),
notmuch_config_get_user_primary_email (config));
- return 0;
+ return EXIT_SUCCESS;
}
int
const char *command_name = NULL;
command_t *command;
char *config_file_name = NULL;
- notmuch_config_t *config;
+ notmuch_config_t *config = NULL;
notmuch_bool_t print_help=FALSE, print_version=FALSE;
int opt_index;
- int ret = 0;
+ int ret;
notmuch_opt_desc_t options[] = {
{ NOTMUCH_OPT_BOOLEAN, &print_help, "help", 'h', 0 },
opt_index = parse_arguments (argc, argv, options, 1);
if (opt_index < 0) {
- /* diagnostics already printed */
- return 1;
+ ret = EXIT_FAILURE;
+ goto DONE;
}
- if (print_help)
- return notmuch_help_command (NULL, argc - 1, &argv[1]);
+ if (print_help) {
+ ret = notmuch_help_command (NULL, argc - 1, &argv[1]);
+ goto DONE;
+ }
if (print_version) {
printf ("notmuch " STRINGIFY(NOTMUCH_VERSION) "\n");
- return 0;
+ ret = EXIT_SUCCESS;
+ goto DONE;
}
if (opt_index < argc)
if (!command) {
fprintf (stderr, "Error: Unknown command '%s' (see \"notmuch help\")\n",
command_name);
- return 1;
+ ret = EXIT_FAILURE;
+ goto DONE;
}
config = notmuch_config_open (local, config_file_name, command->create_config);
- if (!config)
- return 1;
+ if (!config) {
+ ret = EXIT_FAILURE;
+ goto DONE;
+ }
ret = (command->function)(config, argc - opt_index, argv + opt_index);
- notmuch_config_close (config);
+ DONE:
+ if (config)
+ notmuch_config_close (config);
talloc_report = getenv ("NOTMUCH_TALLOC_REPORT");
if (talloc_report && strcmp (talloc_report, "") != 0) {
--- /dev/null
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v1.4.15 (GNU/Linux)
+
+iQGcBAABCAAGBQJSdaDkAAoJEPIClx2kp54sQ54L/ikkvF1fy88hjLitN59v6g2J
+vw85YNRifNHyp/UXI6nt2eXFzyWJiRHuvHFoBgmEsJVxauOKw61Gs2zd53x9Ear4
+MGcQWyiM1cnwX/nD7GvxRQNh33f+FEamTjg+QhG47K0A2YdLWcDC7r9GMatGT11x
+5KE24WQGOqtgQn/9qNtJvkiKIehpRiDTaW/QJ7mTCYeJFjIHJUY8dxyfiTtkJ0z7
+cJ6omehvWSw4STbEg65XJgqykxMdltNEavfvSbAT73FgmkkyXxul0s5hDZ/esd0n
+re3dyDxGt085POiAgPti05a4tJI5EQC2wLBUFri0s2JdMtazcD6yVuHNbVzZ4Do3
+nL/sgwKGUq5wRrPqPWp6HXtZ9zG+/V7hFNrr/l42qGrLqsSh0bqvEnUiwczZLBGy
+NEs4G8VjmfS2cMKePsWaekBAvFUtb47PSB6JIPwpCNvKXDrcCb28eOQVB2atgj1h
+9SktOtWYJhWIQp2YW9iae30Z6lhCcdPRRHTFMQq2nQ==
+=eSMY
+-----END PGP SIGNATURE-----
{
rm -rf ${MAIL_DIR}
- case "$corpus_size" in
- small)
- mail_subdir="mail/enron/bailey-s"
- check_for="${TEST_DIRECTORY}/corpus/$mail_subdir"
- ;;
- medium)
- mail_subdir="mail/notmuch-archive"
- check_for="${TEST_DIRECTORY}/corpus/$mail_subdir"
- ;;
- *)
- mail_subdir=mail
- check_for="${TEST_DIRECTORY}/corpus/$mail_subdir/enron/wolfe-j"
- esac
+ CORPUS_DIR=${TEST_DIRECTORY}/corpus
+ mkdir -p "${CORPUS_DIR}"
- MAIL_CORPUS="${TEST_DIRECTORY}/corpus/$mail_subdir"
- TAG_CORPUS="${TEST_DIRECTORY}/corpus/tags"
+ MAIL_CORPUS="${CORPUS_DIR}/mail.${corpus_size}"
+ TAG_CORPUS="${CORPUS_DIR}/tags"
- args=()
- if [ ! -d "$TAG_CORPUS" ] ; then
- args+=("notmuch-email-corpus/tags")
+ if command -v pixz > /dev/null; then
+ XZ=pixz
+ else
+ XZ=xz
fi
- if [ ! -d "$check_for" ] ; then
- args+=("notmuch-email-corpus/$mail_subdir")
+ if [ ! -d "${CORPUS_DIR}/manifest" ]; then
+
+ printf "Unpacking manifests\n"
+ tar --extract --use-compress-program ${XZ} --strip-components=1 \
+ --directory ${TEST_DIRECTORY}/corpus \
+ --wildcards --file ../download/notmuch-email-corpus-${PERFTEST_VERSION}.tar.xz \
+ 'notmuch-email-corpus/manifest/*'
fi
- if [[ ${#args[@]} > 0 ]]; then
- if command -v pixz > /dev/null; then
- XZ=pixz
+ file_list=$(mktemp file_listXXXXXX)
+ if [ ! -d "$TAG_CORPUS" ] ; then
+ echo "notmuch-email-corpus/tags" >> $file_list
+ fi
+
+ if [ ! -d "$MAIL_CORPUS" ] ; then
+ if [[ "$corpus_size" != "large" ]]; then
+ sed s,^,notmuch-email-corpus/, < \
+ ${TEST_DIRECTORY}/corpus/manifest/MANIFEST.${corpus_size} >> $file_list
else
- XZ=xz
+ echo "notmuch-email-corpus/mail" >> $file_list
fi
+ fi
- printf "Unpacking corpus\n"
- mkdir -p "${TEST_DIRECTORY}/corpus"
+ if [[ -s $file_list ]]; then
+ printf "Unpacking corpus\n"
tar --checkpoint=.5000 --extract --strip-components=1 \
--directory ${TEST_DIRECTORY}/corpus \
--use-compress-program ${XZ} \
--file ../download/notmuch-email-corpus-${PERFTEST_VERSION}.tar.xz \
- "${args[@]}"
+ --anchored --recursion \
+ --files-from $file_list
printf "\n"
+ if [[ ! -d ${MAIL_CORPUS} ]]; then
+ printf "creating link farm\n"
+
+ if [[ "$corpus_size" = large ]]; then
+ cp -rl ${TEST_DIRECTORY}/corpus/mail ${MAIL_CORPUS}
+ else
+ while read -r file; do
+ tdir=${MAIL_CORPUS}/$(dirname $file)
+ mkdir -p $tdir
+ ln ${TEST_DIRECTORY}/corpus/$file $tdir
+ done <${TEST_DIRECTORY}/corpus/manifest/MANIFEST.${corpus_size}
+ fi
+ fi
+
fi
+ rm $file_list
cp -lr $TAG_CORPUS $TMP_DIRECTORY/corpus.tags
cp -lr $MAIL_CORPUS $MAIL_DIR
}
# this should be both a valid Makefile fragment and valid POSIX(ish) shell.
-PERFTEST_VERSION=0.3
+PERFTEST_VERSION=0.4
TEST_EMACS=my-special-emacs TEST_EMACSCLIENT=my-emacsclient ./emacs
make test TEST_EMACS=my-special-emacs TEST_EMACSCLIENT=my-emacsclient
+Quiet Execution
+---------------
+
+Normally, when new script starts and when test PASSes you get a message
+printed on screen. This printing can be disabled by setting the
+NOTMUCH_TEST_QUIET variable to a non-null value. Message on test
+failures and skips are still printed.
+
Skipping Tests
--------------
If, for any reason, you need to skip one or more tests, you can do so
--- /dev/null
+#!/usr/bin/env bash
+#
+# Copyright (c) 2005 Junio C Hamano
+#
+
+test_description='the test framework itself.'
+
+################################################################
+# It appears that people try to run tests without building...
+
+if ! test -x ../notmuch
+then
+ echo >&2 'You do not seem to have built notmuch yet.'
+ exit 1
+fi
+
+. ./test-lib.sh
+
+################################################################
+# Test harness
+test_expect_success 'success is reported like this' '
+ :
+'
+test_set_prereq HAVEIT
+haveit=no
+test_expect_success HAVEIT 'test runs if prerequisite is satisfied' '
+ test_have_prereq HAVEIT &&
+ haveit=yes
+'
+
+clean=no
+test_expect_success 'tests clean up after themselves' '
+ test_when_finished clean=yes
+'
+
+cleaner=no
+test_expect_code 1 'tests clean up even after a failure' '
+ test_when_finished cleaner=yes &&
+ (exit 1)
+'
+
+if test $clean$cleaner != yesyes
+then
+ say "bug in test framework: cleanup commands do not work reliably"
+ exit 1
+fi
+
+test_expect_code 2 'failure to clean up causes the test to fail' '
+ test_when_finished "(exit 2)"
+'
+
+EXPECTED=$TEST_DIRECTORY/test.expected-output
+suppress_diff_date() {
+ sed -e 's/\(.*\-\-\- test-verbose\.4\.\expected\).*/\1/' \
+ -e 's/\(.*\+\+\+ test-verbose\.4\.\output\).*/\1/'
+}
+
+test_begin_subtest "Ensure that test output is suppressed unless the test fails"
+output=$(cd $TEST_DIRECTORY; NOTMUCH_TEST_QUIET= ./test-verbose 2>&1 | suppress_diff_date)
+expected=$(cat $EXPECTED/test-verbose-no | suppress_diff_date)
+test_expect_equal "$output" "$expected"
+
+test_begin_subtest "Ensure that -v does not suppress test output"
+output=$(cd $TEST_DIRECTORY; NOTMUCH_TEST_QUIET= ./test-verbose -v 2>&1 | suppress_diff_date)
+expected=$(cat $EXPECTED/test-verbose-yes | suppress_diff_date)
+# Do not include the results of test-verbose in totals
+rm $TEST_DIRECTORY/test-results/test-verbose
+rm -r $TEST_DIRECTORY/tmp.test-verbose
+test_expect_equal "$output" "$expected"
+
+
+################################################################
+# Test mail store prepared in test-lib.sh
+
+test_expect_success \
+ 'test that mail store was created' \
+ 'test -d "${MAIL_DIR}"'
+
+
+find "${MAIL_DIR}" -type f -print >should-be-empty
+test_expect_success \
+ 'mail store should be empty' \
+ 'cmp -s /dev/null should-be-empty'
+
+test_expect_success \
+ 'NOTMUCH_CONFIG is set and points to an existing file' \
+ 'test -f "${NOTMUCH_CONFIG}"'
+
+test_expect_success \
+ 'PATH is set to this repository' \
+ 'test "`echo $PATH|cut -f1 -d: | sed -e 's,/test/valgrind/bin$,,'`" = "`dirname ${TEST_DIRECTORY}`"'
+
+test_done
--- /dev/null
+#!/usr/bin/env bash
+
+test_description="online help"
+. ./test-lib.sh
+
+test_expect_success 'notmuch --help' 'notmuch --help'
+test_expect_success 'notmuch --help tag' 'notmuch --help tag'
+test_expect_success 'notmuch help' 'notmuch help'
+test_expect_success 'notmuch help tag' 'notmuch help tag'
+test_expect_success 'notmuch --version' 'notmuch --version'
+
+test_done
--- /dev/null
+#!/usr/bin/env bash
+test_description='"notmuch compact"'
+. ./test-lib.sh
+
+add_message '[subject]=One'
+add_message '[subject]=Two'
+add_message '[subject]=Three'
+
+notmuch tag +tag1 \*
+notmuch tag +tag2 subject:Two
+notmuch tag -tag1 +tag3 subject:Three
+
+test_expect_success "Running compact" "notmuch compact --backup=${TEST_DIRECTORY}/xapian.old"
+
+test_begin_subtest "Compact preserves database"
+output=$(notmuch search \* | notmuch_search_sanitize)
+test_expect_equal "$output" "\
+thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; One (inbox tag1 unread)
+thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Two (inbox tag1 tag2 unread)
+thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Three (inbox tag3 unread)"
+
+test_expect_success 'Restoring Backup' \
+ 'rm -Rf ${MAIL_DIR}/.notmuch/xapian &&
+ mv ${TEST_DIRECTORY}/xapian.old ${MAIL_DIR}/.notmuch/xapian'
+
+test_begin_subtest "Checking restored backup"
+output=$(notmuch search \* | notmuch_search_sanitize)
+test_expect_equal "$output" "\
+thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; One (inbox tag1 unread)
+thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Two (inbox tag1 tag2 unread)
+thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Three (inbox tag3 unread)"
+
+test_done
--- /dev/null
+#!/usr/bin/env bash
+
+test_description='"notmuch config"'
+. ./test-lib.sh
+
+test_begin_subtest "Get string value"
+test_expect_equal "$(notmuch config get user.name)" "Notmuch Test Suite"
+
+test_begin_subtest "Get list value"
+test_expect_equal "$(notmuch config get new.tags)" "\
+unread
+inbox"
+
+test_begin_subtest "Set string value"
+notmuch config set foo.string "this is a string value"
+test_expect_equal "$(notmuch config get foo.string)" "this is a string value"
+
+test_begin_subtest "Set string value again"
+notmuch config set foo.string "this is another string value"
+test_expect_equal "$(notmuch config get foo.string)" "this is another string value"
+
+test_begin_subtest "Set list value"
+notmuch config set foo.list this "is a" "list value"
+test_expect_equal "$(notmuch config get foo.list)" "\
+this
+is a
+list value"
+
+test_begin_subtest "Set list value again"
+notmuch config set foo.list this "is another" "list value"
+test_expect_equal "$(notmuch config get foo.list)" "\
+this
+is another
+list value"
+
+test_begin_subtest "Remove key"
+notmuch config set foo.remove baz
+notmuch config set foo.remove
+test_expect_equal "$(notmuch config get foo.remove)" ""
+
+test_begin_subtest "Remove non-existent key"
+notmuch config set foo.nonexistent
+test_expect_equal "$(notmuch config get foo.nonexistent)" ""
+
+test_begin_subtest "List all items"
+notmuch config set database.path "/canonical/path"
+output=$(notmuch config list)
+test_expect_equal "$output" "\
+database.path=/canonical/path
+user.name=Notmuch Test Suite
+user.primary_email=test_suite@notmuchmail.org
+user.other_email=test_suite_other@notmuchmail.org;test_suite@otherdomain.org
+new.tags=unread;inbox;
+new.ignore=
+search.exclude_tags=
+maildir.synchronize_flags=true
+foo.string=this is another string value
+foo.list=this;is another;list value;"
+
+test_begin_subtest "Top level --config=FILE option"
+cp "${NOTMUCH_CONFIG}" alt-config
+notmuch --config=alt-config config set user.name "Another Name"
+test_expect_equal "$(notmuch --config=alt-config config get user.name)" \
+ "Another Name"
+
+test_begin_subtest "Top level --config=FILE option changed the right file"
+test_expect_equal "$(notmuch config get user.name)" \
+ "Notmuch Test Suite"
+
+test_begin_subtest "Read config file through a symlink"
+ln -s alt-config alt-config-link
+test_expect_equal "$(notmuch --config=alt-config-link config get user.name)" \
+ "Another Name"
+
+test_begin_subtest "Write config file through a symlink"
+notmuch --config=alt-config-link config set user.name "Link Name"
+test_expect_equal "$(notmuch --config=alt-config-link config get user.name)" \
+ "Link Name"
+
+test_begin_subtest "Writing config file through symlink follows symlink"
+test_expect_equal "$(readlink alt-config-link)" "alt-config"
+
+test_done
--- /dev/null
+#!/usr/bin/env bash
+
+test_description='"notmuch setup"'
+. ./test-lib.sh
+
+test_begin_subtest "Create a new config interactively"
+notmuch --config=new-notmuch-config > /dev/null <<EOF
+Test Suite
+test.suite@example.com
+another.suite@example.com
+
+/path/to/maildir
+foo bar
+baz
+EOF
+output=$(notmuch --config=new-notmuch-config config list)
+test_expect_equal "$output" "\
+database.path=/path/to/maildir
+user.name=Test Suite
+user.primary_email=test.suite@example.com
+user.other_email=another.suite@example.com;
+new.tags=foo;bar;
+new.ignore=
+search.exclude_tags=baz;
+maildir.synchronize_flags=true"
+
+test_done
--- /dev/null
+#!/usr/bin/env bash
+test_description='"notmuch new" in several variations'
+. ./test-lib.sh
+
+test_begin_subtest "No new messages"
+output=$(NOTMUCH_NEW)
+test_expect_equal "$output" "No new mail."
+
+
+test_begin_subtest "Single new message"
+generate_message
+output=$(NOTMUCH_NEW)
+test_expect_equal "$output" "Added 1 new message to the database."
+
+
+test_begin_subtest "Multiple new messages"
+generate_message
+generate_message
+output=$(NOTMUCH_NEW)
+test_expect_equal "$output" "Added 2 new messages to the database."
+
+
+test_begin_subtest "No new messages (non-empty DB)"
+output=$(NOTMUCH_NEW)
+test_expect_equal "$output" "No new mail."
+
+
+test_begin_subtest "New directories"
+rm -rf "${MAIL_DIR}"/* "${MAIL_DIR}"/.notmuch
+mkdir "${MAIL_DIR}"/def
+mkdir "${MAIL_DIR}"/ghi
+generate_message [dir]=def
+
+output=$(NOTMUCH_NEW)
+test_expect_equal "$output" "Added 1 new message to the database."
+
+
+test_begin_subtest "Alternate inode order"
+
+rm -rf "${MAIL_DIR}"/.notmuch
+mv "${MAIL_DIR}"/ghi "${MAIL_DIR}"/abc
+rm "${MAIL_DIR}"/def/*
+generate_message [dir]=abc
+
+output=$(NOTMUCH_NEW)
+test_expect_equal "$output" "Added 1 new message to the database."
+
+
+test_begin_subtest "Message moved in"
+rm -rf "${MAIL_DIR}"/* "${MAIL_DIR}"/.notmuch
+generate_message
+tmp_msg_filename=tmp/"$gen_msg_filename"
+mkdir -p "$(dirname "$tmp_msg_filename")"
+mv "$gen_msg_filename" "$tmp_msg_filename"
+notmuch new > /dev/null
+mv "$tmp_msg_filename" "$gen_msg_filename"
+output=$(NOTMUCH_NEW)
+test_expect_equal "$output" "Added 1 new message to the database."
+
+
+test_begin_subtest "Renamed message"
+
+generate_message
+notmuch new > /dev/null
+mv "$gen_msg_filename" "${gen_msg_filename}"-renamed
+output=$(NOTMUCH_NEW)
+test_expect_equal "$output" "No new mail. Detected 1 file rename."
+
+
+test_begin_subtest "Deleted message"
+
+rm "${gen_msg_filename}"-renamed
+output=$(NOTMUCH_NEW)
+test_expect_equal "$output" "No new mail. Removed 1 message."
+
+
+test_begin_subtest "Renamed directory"
+
+generate_message [dir]=dir
+generate_message [dir]=dir
+generate_message [dir]=dir
+
+notmuch new > /dev/null
+
+mv "${MAIL_DIR}"/dir "${MAIL_DIR}"/dir-renamed
+
+output=$(NOTMUCH_NEW)
+test_expect_equal "$output" "No new mail. Detected 3 file renames."
+
+
+test_begin_subtest "Deleted directory"
+
+rm -rf "${MAIL_DIR}"/dir-renamed
+
+output=$(NOTMUCH_NEW)
+test_expect_equal "$output" "No new mail. Removed 3 messages."
+
+
+test_begin_subtest "New directory (at end of list)"
+
+generate_message [dir]=zzz
+generate_message [dir]=zzz
+generate_message [dir]=zzz
+
+output=$(NOTMUCH_NEW)
+test_expect_equal "$output" "Added 3 new messages to the database."
+
+
+test_begin_subtest "Deleted directory (end of list)"
+
+rm -rf "${MAIL_DIR}"/zzz
+
+output=$(NOTMUCH_NEW)
+test_expect_equal "$output" "No new mail. Removed 3 messages."
+
+
+test_begin_subtest "New symlink to directory"
+
+rm -rf "${MAIL_DIR}"/.notmuch
+mv "${MAIL_DIR}" "${TMP_DIRECTORY}"/actual_maildir
+
+mkdir "${MAIL_DIR}"
+ln -s "${TMP_DIRECTORY}"/actual_maildir "${MAIL_DIR}"/symlink
+
+output=$(NOTMUCH_NEW)
+test_expect_equal "$output" "Added 1 new message to the database."
+
+
+test_begin_subtest "New symlink to a file"
+generate_message
+external_msg_filename="${TMP_DIRECTORY}"/external/"$(basename "$gen_msg_filename")"
+mkdir -p "$(dirname "$external_msg_filename")"
+mv "$gen_msg_filename" "$external_msg_filename"
+ln -s "$external_msg_filename" "$gen_msg_filename"
+output=$(NOTMUCH_NEW)
+test_expect_equal "$output" "Added 1 new message to the database."
+
+
+test_begin_subtest "Broken symlink aborts"
+ln -s does-not-exist "${MAIL_DIR}/broken"
+output=$(NOTMUCH_NEW 2>&1)
+test_expect_equal "$output" \
+"Error reading file ${MAIL_DIR}/broken: No such file or directory
+Note: A fatal error was encountered: Something went wrong trying to read or write a file
+No new mail."
+rm "${MAIL_DIR}/broken"
+
+
+test_begin_subtest "New two-level directory"
+
+generate_message [dir]=two/levels
+generate_message [dir]=two/levels
+generate_message [dir]=two/levels
+
+output=$(NOTMUCH_NEW)
+test_expect_equal "$output" "Added 3 new messages to the database."
+
+
+test_begin_subtest "Deleted two-level directory"
+
+rm -rf "${MAIL_DIR}"/two
+
+output=$(NOTMUCH_NEW)
+test_expect_equal "$output" "No new mail. Removed 3 messages."
+
+test_begin_subtest "Support single-message mbox (deprecated)"
+cat > "${MAIL_DIR}"/mbox_file1 <<EOF
+From test_suite@notmuchmail.org Fri Jan 5 15:43:57 2001
+From: Notmuch Test Suite <test_suite@notmuchmail.org>
+To: Notmuch Test Suite <test_suite@notmuchmail.org>
+Subject: Test mbox message 1
+
+Body.
+EOF
+output=$(NOTMUCH_NEW 2>&1)
+test_expect_equal "$output" \
+"Warning: ${MAIL_DIR}/mbox_file1 is an mbox containing a single message,
+likely caused by misconfigured mail delivery. Support for single-message
+mboxes is deprecated and may be removed in the future.
+Added 1 new message to the database."
+
+# This test requires that notmuch new has been run at least once.
+test_begin_subtest "Skip and report non-mail files"
+generate_message
+mkdir -p "${MAIL_DIR}"/.git && touch "${MAIL_DIR}"/.git/config
+touch "${MAIL_DIR}"/ignored_file
+touch "${MAIL_DIR}"/.ignored_hidden_file
+cat > "${MAIL_DIR}"/mbox_file <<EOF
+From test_suite@notmuchmail.org Fri Jan 5 15:43:57 2001
+From: Notmuch Test Suite <test_suite@notmuchmail.org>
+To: Notmuch Test Suite <test_suite@notmuchmail.org>
+Subject: Test mbox message 1
+
+Body.
+
+From test_suite@notmuchmail.org Fri Jan 5 15:43:57 2001
+From: Notmuch Test Suite <test_suite@notmuchmail.org>
+To: Notmuch Test Suite <test_suite@notmuchmail.org>
+Subject: Test mbox message 2
+
+Body 2.
+EOF
+output=$(NOTMUCH_NEW 2>&1)
+test_expect_equal "$output" \
+"Note: Ignoring non-mail file: ${MAIL_DIR}/.git/config
+Note: Ignoring non-mail file: ${MAIL_DIR}/.ignored_hidden_file
+Note: Ignoring non-mail file: ${MAIL_DIR}/ignored_file
+Note: Ignoring non-mail file: ${MAIL_DIR}/mbox_file
+Added 1 new message to the database."
+rm "${MAIL_DIR}"/mbox_file
+
+test_begin_subtest "Ignore files and directories specified in new.ignore"
+generate_message
+notmuch config set new.ignore .git ignored_file .ignored_hidden_file
+touch "${MAIL_DIR}"/.git # change .git's mtime for notmuch new to rescan.
+output=$(NOTMUCH_NEW 2>&1)
+test_expect_equal "$output" "Added 1 new message to the database."
+
+test_begin_subtest "Ignore files and directories specified in new.ignore (multiple occurrences)"
+notmuch config set new.ignore .git ignored_file .ignored_hidden_file
+notmuch new > /dev/null # ensure that files/folders will be printed in ASCII order.
+touch "${MAIL_DIR}"/.git # change .git's mtime for notmuch new to rescan.
+touch "${MAIL_DIR}" # likewise for MAIL_DIR
+mkdir -p "${MAIL_DIR}"/one/two/three/.git
+touch "${MAIL_DIR}"/{one,one/two,one/two/three}/ignored_file
+output=$(NOTMUCH_NEW --debug 2>&1 | sort)
+test_expect_equal "$output" \
+"(D) add_files_recursive, pass 1: explicitly ignoring ${MAIL_DIR}/.git
+(D) add_files_recursive, pass 1: explicitly ignoring ${MAIL_DIR}/.ignored_hidden_file
+(D) add_files_recursive, pass 1: explicitly ignoring ${MAIL_DIR}/ignored_file
+(D) add_files_recursive, pass 1: explicitly ignoring ${MAIL_DIR}/one/ignored_file
+(D) add_files_recursive, pass 1: explicitly ignoring ${MAIL_DIR}/one/two/ignored_file
+(D) add_files_recursive, pass 1: explicitly ignoring ${MAIL_DIR}/one/two/three/.git
+(D) add_files_recursive, pass 1: explicitly ignoring ${MAIL_DIR}/one/two/three/ignored_file
+(D) add_files_recursive, pass 2: explicitly ignoring ${MAIL_DIR}/.git
+(D) add_files_recursive, pass 2: explicitly ignoring ${MAIL_DIR}/.ignored_hidden_file
+(D) add_files_recursive, pass 2: explicitly ignoring ${MAIL_DIR}/ignored_file
+(D) add_files_recursive, pass 2: explicitly ignoring ${MAIL_DIR}/one/ignored_file
+(D) add_files_recursive, pass 2: explicitly ignoring ${MAIL_DIR}/one/two/ignored_file
+(D) add_files_recursive, pass 2: explicitly ignoring ${MAIL_DIR}/one/two/three/.git
+(D) add_files_recursive, pass 2: explicitly ignoring ${MAIL_DIR}/one/two/three/ignored_file
+No new mail."
+
+
+test_begin_subtest "Don't stop for ignored broken symlinks"
+notmuch config set new.ignore .git ignored_file .ignored_hidden_file broken_link
+ln -s i_do_not_exist "${MAIL_DIR}"/broken_link
+output=$(NOTMUCH_NEW 2>&1)
+test_expect_equal "$output" "No new mail."
+
+test_begin_subtest "Quiet: No new mail."
+output=$(NOTMUCH_NEW --quiet)
+test_expect_equal "$output" ""
+
+test_begin_subtest "Quiet: new, removed and renamed messages."
+# new
+generate_message
+# deleted
+notmuch search --format=text0 --output=files --limit=1 '*' | xargs -0 rm
+# moved
+mkdir "${MAIL_DIR}"/moved_messages
+notmuch search --format=text0 --output=files --offset=1 --limit=1 '*' | xargs -0 -I {} mv {} "${MAIL_DIR}"/moved_messages
+output=$(NOTMUCH_NEW --quiet)
+test_expect_equal "$output" ""
+
+test_done
--- /dev/null
+#!/usr/bin/env bash
+test_description='"notmuch count" for messages and threads'
+. ./test-lib.sh
+
+add_email_corpus
+
+# Note: The 'wc -l' results below are wrapped in arithmetic evaluation
+# $((...)) to strip whitespace. This is for portability, as 'wc -l'
+# emits whitespace on some BSD variants.
+
+test_begin_subtest "message count is the default for notmuch count"
+test_expect_equal \
+ "$((`notmuch search --output=messages '*' | wc -l`))" \
+ "`notmuch count '*'`"
+
+test_begin_subtest "message count with --output=messages"
+test_expect_equal \
+ "$((`notmuch search --output=messages '*' | wc -l`))" \
+ "`notmuch count --output=messages '*'`"
+
+test_begin_subtest "thread count with --output=threads"
+test_expect_equal \
+ "$((`notmuch search --output=threads '*' | wc -l`))" \
+ "`notmuch count --output=threads '*'`"
+
+test_begin_subtest "thread count is the default for notmuch search"
+test_expect_equal \
+ "$((`notmuch search '*' | wc -l`))" \
+ "`notmuch count --output=threads '*'`"
+
+test_begin_subtest "files count"
+test_expect_equal \
+ "$((`notmuch search --output=files '*' | wc -l`))" \
+ "`notmuch count --output=files '*'`"
+
+test_begin_subtest "files count for a duplicate message-id"
+test_expect_equal \
+ "2" \
+ "`notmuch count --output=files id:20091117232137.GA7669@griffis1.net`"
+
+test_begin_subtest "count with no matching messages"
+test_expect_equal \
+ "0" \
+ "`notmuch count --output=messages from:cworth and not from:cworth`"
+
+test_begin_subtest "count with no matching threads"
+test_expect_equal \
+ "0" \
+ "`notmuch count --output=threads from:cworth and not from:cworth`"
+
+test_begin_subtest "message count is the default for batch count"
+notmuch count --batch >OUTPUT <<EOF
+
+from:cworth
+EOF
+notmuch count --output=messages >EXPECTED
+notmuch count --output=messages from:cworth >>EXPECTED
+test_expect_equal_file EXPECTED OUTPUT
+
+test_begin_subtest "batch message count"
+notmuch count --batch --output=messages >OUTPUT <<EOF
+from:cworth
+
+tag:inbox
+EOF
+notmuch count --output=messages from:cworth >EXPECTED
+notmuch count --output=messages >>EXPECTED
+notmuch count --output=messages tag:inbox >>EXPECTED
+test_expect_equal_file EXPECTED OUTPUT
+
+test_begin_subtest "batch thread count"
+notmuch count --batch --output=threads >OUTPUT <<EOF
+
+from:cworth
+from:cworth and not from:cworth
+foo
+EOF
+notmuch count --output=threads >EXPECTED
+notmuch count --output=threads from:cworth >>EXPECTED
+notmuch count --output=threads from:cworth and not from:cworth >>EXPECTED
+notmuch count --output=threads foo >>EXPECTED
+test_expect_equal_file EXPECTED OUTPUT
+
+test_begin_subtest "batch message count with input file"
+cat >INPUT <<EOF
+from:cworth
+
+tag:inbox
+EOF
+notmuch count --input=INPUT --output=messages >OUTPUT
+notmuch count --output=messages from:cworth >EXPECTED
+notmuch count --output=messages >>EXPECTED
+notmuch count --output=messages tag:inbox >>EXPECTED
+test_expect_equal_file EXPECTED OUTPUT
+
+
+test_done
--- /dev/null
+#!/usr/bin/env bash
+test_description='"notmuch insert"'
+. ./test-lib.sh
+
+# Create directories and database before inserting.
+mkdir -p "$MAIL_DIR"/{cur,new,tmp}
+mkdir -p "$MAIL_DIR"/Drafts/{cur,new,tmp}
+notmuch new > /dev/null
+
+# We use generate_message to create the temporary message files.
+# They happen to be in the mail directory already but that is okay
+# since we do not call notmuch new hereafter.
+
+gen_insert_msg() {
+ generate_message \
+ "[subject]=\"insert-subject\"" \
+ "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" \
+ "[body]=\"insert-message\""
+}
+
+test_expect_code 1 "Insert zero-length file" \
+ "notmuch insert < /dev/null"
+
+# This test is a proxy for other errors that may occur while trying to
+# add a message to the notmuch database, e.g. database locked.
+test_expect_code 0 "Insert non-message" \
+ "echo bad_message | notmuch insert"
+
+test_begin_subtest "Database empty so far"
+test_expect_equal "0" "`notmuch count --output=messages '*'`"
+
+test_begin_subtest "Insert message"
+gen_insert_msg
+notmuch insert < "$gen_msg_filename"
+cur_msg_filename=$(notmuch search --output=files "subject:insert-subject")
+test_expect_equal_file "$cur_msg_filename" "$gen_msg_filename"
+
+test_begin_subtest "Insert message adds default tags"
+output=$(notmuch show --format=json "subject:insert-subject")
+expected='[[[{
+ "id": "'"${gen_msg_id}"'",
+ "match": true,
+ "excluded": false,
+ "filename": "'"${cur_msg_filename}"'",
+ "timestamp": 946728000,
+ "date_relative": "2000-01-01",
+ "tags": ["inbox","unread"],
+ "headers": {
+ "Subject": "insert-subject",
+ "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
+ "To": "Notmuch Test Suite <test_suite@notmuchmail.org>",
+ "Date": "Sat, 01 Jan 2000 12:00:00 +0000"},
+ "body": [{"id": 1,
+ "content-type": "text/plain",
+ "content": "insert-message\n"}]},
+ []]]]'
+test_expect_equal_json "$output" "$expected"
+
+test_begin_subtest "Insert duplicate message"
+notmuch insert +duptag -unread < "$gen_msg_filename"
+output=$(notmuch search --output=files "subject:insert-subject" | wc -l)
+test_expect_equal "$output" 2
+
+test_begin_subtest "Duplicate message does not change tags"
+output=$(notmuch search --format=json --output=tags "subject:insert-subject")
+test_expect_equal_json "$output" '["inbox", "unread"]'
+
+test_begin_subtest "Insert message, add tag"
+gen_insert_msg
+notmuch insert +custom < "$gen_msg_filename"
+output=$(notmuch search --output=messages tag:custom)
+test_expect_equal "$output" "id:$gen_msg_id"
+
+test_begin_subtest "Insert message, add/remove tags"
+gen_insert_msg
+notmuch insert +custom -unread < "$gen_msg_filename"
+output=$(notmuch search --output=messages tag:custom NOT tag:unread)
+test_expect_equal "$output" "id:$gen_msg_id"
+
+test_begin_subtest "Insert message with default tags stays in new/"
+gen_insert_msg
+notmuch insert < "$gen_msg_filename"
+output=$(notmuch search --output=files id:$gen_msg_id)
+dirname=$(dirname "$output")
+test_expect_equal "$dirname" "$MAIL_DIR/new"
+
+test_begin_subtest "Insert message with non-maildir synced tags stays in new/"
+gen_insert_msg
+notmuch insert +custom -inbox < "$gen_msg_filename"
+output=$(notmuch search --output=files id:$gen_msg_id)
+dirname=$(dirname "$output")
+test_expect_equal "$dirname" "$MAIL_DIR/new"
+
+test_begin_subtest "Insert message with custom new.tags goes to cur/"
+OLDCONFIG=$(notmuch config get new.tags)
+notmuch config set new.tags test
+gen_insert_msg
+notmuch insert < "$gen_msg_filename"
+output=$(notmuch search --output=files id:$gen_msg_id)
+dirname=$(dirname "$output")
+notmuch config set new.tags $OLDCONFIG
+test_expect_equal "$dirname" "$MAIL_DIR/cur"
+
+# additional check on the previous message
+test_begin_subtest "Insert message with custom new.tags actually gets the tags"
+output=$(notmuch search --output=tags id:$gen_msg_id)
+test_expect_equal "$output" "test"
+
+test_begin_subtest "Insert message with maildir synced tags goes to cur/"
+gen_insert_msg
+notmuch insert +flagged < "$gen_msg_filename"
+output=$(notmuch search --output=files id:$gen_msg_id)
+dirname=$(dirname "$output")
+test_expect_equal "$dirname" "$MAIL_DIR/cur"
+
+test_begin_subtest "Insert message with maildir sync off goes to new/"
+OLDCONFIG=$(notmuch config get maildir.synchronize_flags)
+notmuch config set maildir.synchronize_flags false
+gen_insert_msg
+notmuch insert +flagged < "$gen_msg_filename"
+output=$(notmuch search --output=files id:$gen_msg_id)
+dirname=$(dirname "$output")
+notmuch config set maildir.synchronize_flags $OLDCONFIG
+test_expect_equal "$dirname" "$MAIL_DIR/new"
+
+test_begin_subtest "Insert message into folder"
+gen_insert_msg
+notmuch insert --folder=Drafts < "$gen_msg_filename"
+output=$(notmuch search --output=files folder:Drafts)
+dirname=$(dirname "$output")
+test_expect_equal "$dirname" "$MAIL_DIR/Drafts/new"
+
+test_begin_subtest "Insert message into folder, add/remove tags"
+gen_insert_msg
+notmuch insert --folder=Drafts +draft -unread < "$gen_msg_filename"
+output=$(notmuch search --output=messages folder:Drafts tag:draft NOT tag:unread)
+test_expect_equal "$output" "id:$gen_msg_id"
+
+gen_insert_msg
+test_expect_code 1 "Insert message into non-existent folder" \
+ "notmuch insert --folder=nonesuch < $gen_msg_filename"
+
+test_begin_subtest "Insert message, create folder"
+gen_insert_msg
+notmuch insert --folder=F --create-folder +folder < "$gen_msg_filename"
+output=$(notmuch search --output=files folder:F tag:folder)
+basename=$(basename "$output")
+test_expect_equal_file "$gen_msg_filename" "$MAIL_DIR/F/new/${basename}"
+
+test_begin_subtest "Insert message, create subfolder"
+gen_insert_msg
+notmuch insert --folder=F/G/H/I/J --create-folder +folder < "$gen_msg_filename"
+output=$(notmuch search --output=files folder:F/G/H/I/J tag:folder)
+basename=$(basename "$output")
+test_expect_equal_file "$gen_msg_filename" "${MAIL_DIR}/F/G/H/I/J/new/${basename}"
+
+test_begin_subtest "Insert message, create existing subfolder"
+gen_insert_msg
+notmuch insert --folder=F/G/H/I/J --create-folder +folder < "$gen_msg_filename"
+output=$(notmuch count folder:F/G/H/I/J tag:folder)
+test_expect_equal "$output" "2"
+
+gen_insert_msg
+test_expect_code 1 "Insert message, create invalid subfolder" \
+ "notmuch insert --folder=../G --create-folder $gen_msg_filename"
+
+test_done
--- /dev/null
+#!/usr/bin/env bash
+test_description='"notmuch search" in several variations'
+. ./test-lib.sh
+
+add_email_corpus
+
+test_begin_subtest "Search body"
+add_message '[subject]="body search"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"' [body]=bodysearchtest
+output=$(notmuch search bodysearchtest | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; body search (inbox unread)"
+
+test_begin_subtest "Search by from:"
+add_message '[subject]="search by from"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"' [from]=searchbyfrom
+output=$(notmuch search from:searchbyfrom | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2000-01-01 [1/1] searchbyfrom; search by from (inbox unread)"
+
+test_begin_subtest "Search by to:"
+add_message '[subject]="search by to"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"' [to]=searchbyto
+output=$(notmuch search to:searchbyto | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; search by to (inbox unread)"
+
+test_begin_subtest "Search by subject:"
+add_message [subject]=subjectsearchtest '[date]="Sat, 01 Jan 2000 12:00:00 -0000"'
+output=$(notmuch search subject:subjectsearchtest | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; subjectsearchtest (inbox unread)"
+
+test_begin_subtest "Search by subject (utf-8):"
+add_message [subject]=utf8-sübjéct '[date]="Sat, 01 Jan 2000 12:00:00 -0000"'
+output=$(notmuch search subject:utf8-sübjéct | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; utf8-sübjéct (inbox unread)"
+
+test_begin_subtest "Search by id:"
+add_message '[subject]="search by id"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"'
+output=$(notmuch search id:${gen_msg_id} | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; search by id (inbox unread)"
+
+test_begin_subtest "Search by tag:"
+add_message '[subject]="search by tag"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"'
+notmuch tag +searchbytag id:${gen_msg_id}
+output=$(notmuch search tag:searchbytag | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; search by tag (inbox searchbytag unread)"
+
+test_begin_subtest "Search by thread:"
+add_message '[subject]="search by thread"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"'
+thread_id=$(notmuch search id:${gen_msg_id} | sed -e "s/thread:\([a-f0-9]*\).*/\1/")
+output=$(notmuch search thread:${thread_id} | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; search by thread (inbox unread)"
+
+test_begin_subtest "Search body (phrase)"
+add_message '[subject]="body search (phrase)"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"' '[body]="body search (phrase)"'
+add_message '[subject]="negative result"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"' '[body]="This phrase should not match the body search"'
+output=$(notmuch search '"body search (phrase)"' | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; body search (phrase) (inbox unread)"
+
+test_begin_subtest "Search by from: (address)"
+add_message '[subject]="search by from (address)"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"' [from]=searchbyfrom@example.com
+output=$(notmuch search from:searchbyfrom@example.com | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2000-01-01 [1/1] searchbyfrom@example.com; search by from (address) (inbox unread)"
+
+test_begin_subtest "Search by from: (name)"
+add_message '[subject]="search by from (name)"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"' '[from]="Search By From Name <test@example.com>"'
+output=$(notmuch search from:"Search By From Name" | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2000-01-01 [1/1] Search By From Name; search by from (name) (inbox unread)"
+
+test_begin_subtest "Search by to: (address)"
+add_message '[subject]="search by to (address)"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"' [to]=searchbyto@example.com
+output=$(notmuch search to:searchbyto@example.com | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; search by to (address) (inbox unread)"
+
+test_begin_subtest "Search by to: (name)"
+add_message '[subject]="search by to (name)"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"' '[to]="Search By To Name <test@example.com>"'
+output=$(notmuch search to:"Search By To Name" | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; search by to (name) (inbox unread)"
+
+test_begin_subtest "Search by subject: (phrase)"
+add_message '[subject]="subject search test (phrase)"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"'
+add_message '[subject]="this phrase should not match the subject search test"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"'
+output=$(notmuch search 'subject:"subject search test (phrase)"' | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; subject search test (phrase) (inbox unread)"
+
+test_begin_subtest 'Search for all messages ("*")'
+notmuch search '*' | notmuch_search_sanitize > OUTPUT
+cat <<EOF >EXPECTED
+thread:XXX 2010-12-29 [1/1] François Boulogne; [aur-general] Guidelines: cp, mkdir vs install (inbox unread)
+thread:XXX 2010-12-16 [1/1] Olivier Berger; Essai accentué (inbox unread)
+thread:XXX 2009-11-18 [1/1] Chris Wilson; [notmuch] [PATCH 1/2] Makefile: evaluate pkg-config once (inbox unread)
+thread:XXX 2009-11-18 [2/2] Alex Botero-Lowry, Carl Worth; [notmuch] [PATCH] Error out if no query is supplied to search instead of going into an infinite loop (attachment inbox unread)
+thread:XXX 2009-11-18 [2/2] Ingmar Vanhassel, Carl Worth; [notmuch] [PATCH] Typsos (inbox unread)
+thread:XXX 2009-11-18 [3/3] Adrian Perez de Castro, Keith Packard, Carl Worth; [notmuch] Introducing myself (inbox signed unread)
+thread:XXX 2009-11-18 [3/3] Israel Herraiz, Keith Packard, Carl Worth; [notmuch] New to the list (inbox unread)
+thread:XXX 2009-11-18 [3/3] Jan Janak, Carl Worth; [notmuch] What a great idea! (inbox unread)
+thread:XXX 2009-11-18 [2/2] Jan Janak, Carl Worth; [notmuch] [PATCH] Older versions of install do not support -C. (inbox unread)
+thread:XXX 2009-11-18 [3/3] Aron Griffis, Keith Packard, Carl Worth; [notmuch] archive (inbox unread)
+thread:XXX 2009-11-18 [2/2] Keith Packard, Carl Worth; [notmuch] [PATCH] Make notmuch-show 'X' (and 'x') commands remove inbox (and unread) tags (inbox unread)
+thread:XXX 2009-11-18 [7/7] Lars Kellogg-Stedman, Mikhail Gusarov, Keith Packard, Carl Worth; [notmuch] Working with Maildir storage? (inbox signed unread)
+thread:XXX 2009-11-18 [5/5] Mikhail Gusarov, Carl Worth, Keith Packard; [notmuch] [PATCH 1/2] Close message file after parsing message headers (inbox unread)
+thread:XXX 2009-11-18 [2/2] Keith Packard, Alexander Botero-Lowry; [notmuch] [PATCH] Create a default notmuch-show-hook that highlights URLs and uses word-wrap (inbox unread)
+thread:XXX 2009-11-18 [1/1] Alexander Botero-Lowry; [notmuch] request for pull (inbox unread)
+thread:XXX 2009-11-18 [4/4] Jjgod Jiang, Alexander Botero-Lowry; [notmuch] Mac OS X/Darwin compatibility issues (inbox unread)
+thread:XXX 2009-11-18 [1/1] Rolland Santimano; [notmuch] Link to mailing list archives ? (inbox unread)
+thread:XXX 2009-11-18 [1/1] Jan Janak; [notmuch] [PATCH] notmuch new: Support for conversion of spool subdirectories into tags (inbox unread)
+thread:XXX 2009-11-18 [1/1] Stewart Smith; [notmuch] [PATCH] count_files: sort directory in inode order before statting (inbox unread)
+thread:XXX 2009-11-18 [1/1] Stewart Smith; [notmuch] [PATCH 2/2] Read mail directory in inode number order (inbox unread)
+thread:XXX 2009-11-18 [1/1] Stewart Smith; [notmuch] [PATCH] Fix linking with gcc to use g++ to link in C++ libs. (inbox unread)
+thread:XXX 2009-11-18 [2/2] Lars Kellogg-Stedman; [notmuch] "notmuch help" outputs to stderr? (attachment inbox signed unread)
+thread:XXX 2009-11-17 [1/1] Mikhail Gusarov; [notmuch] [PATCH] Handle rename of message file (inbox unread)
+thread:XXX 2009-11-17 [2/2] Alex Botero-Lowry, Carl Worth; [notmuch] preliminary FreeBSD support (attachment inbox unread)
+thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; body search (inbox unread)
+thread:XXX 2000-01-01 [1/1] searchbyfrom; search by from (inbox unread)
+thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; search by to (inbox unread)
+thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; subjectsearchtest (inbox unread)
+thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; utf8-sübjéct (inbox unread)
+thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; search by id (inbox unread)
+thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; search by tag (inbox searchbytag unread)
+thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; search by thread (inbox unread)
+thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; body search (phrase) (inbox unread)
+thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; negative result (inbox unread)
+thread:XXX 2000-01-01 [1/1] searchbyfrom@example.com; search by from (address) (inbox unread)
+thread:XXX 2000-01-01 [1/1] Search By From Name; search by from (name) (inbox unread)
+thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; search by to (address) (inbox unread)
+thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; search by to (name) (inbox unread)
+thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; subject search test (phrase) (inbox unread)
+thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; this phrase should not match the subject search test (inbox unread)
+EOF
+test_expect_equal_file OUTPUT EXPECTED
+
+test_begin_subtest "Search body (utf-8):"
+add_message '[subject]="utf8-message-body-subject"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"' '[body]="message body utf8: bödý"'
+output=$(notmuch search "bödý" | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; utf8-message-body-subject (inbox unread)"
+
+test_done
--- /dev/null
+#!/usr/bin/env bash
+test_description='various settings for "notmuch search --output="'
+. ./test-lib.sh
+
+add_email_corpus
+
+test_begin_subtest "--output=threads"
+notmuch search --output=threads '*' | sed -e s/thread:.*/thread:THREADID/ >OUTPUT
+cat <<EOF >EXPECTED
+thread:THREADID
+thread:THREADID
+thread:THREADID
+thread:THREADID
+thread:THREADID
+thread:THREADID
+thread:THREADID
+thread:THREADID
+thread:THREADID
+thread:THREADID
+thread:THREADID
+thread:THREADID
+thread:THREADID
+thread:THREADID
+thread:THREADID
+thread:THREADID
+thread:THREADID
+thread:THREADID
+thread:THREADID
+thread:THREADID
+thread:THREADID
+thread:THREADID
+thread:THREADID
+thread:THREADID
+EOF
+test_expect_equal_file OUTPUT EXPECTED
+
+test_begin_subtest "--output=threads --format=json"
+notmuch search --format=json --output=threads '*' | sed -e s/\".*\"/\"THREADID\"/ >OUTPUT
+cat <<EOF >EXPECTED
+["THREADID",
+"THREADID",
+"THREADID",
+"THREADID",
+"THREADID",
+"THREADID",
+"THREADID",
+"THREADID",
+"THREADID",
+"THREADID",
+"THREADID",
+"THREADID",
+"THREADID",
+"THREADID",
+"THREADID",
+"THREADID",
+"THREADID",
+"THREADID",
+"THREADID",
+"THREADID",
+"THREADID",
+"THREADID",
+"THREADID",
+"THREADID"]
+EOF
+test_expect_equal_json "$(cat OUTPUT)" "$(cat EXPECTED)"
+
+test_begin_subtest "--output=messages"
+notmuch search --output=messages '*' >OUTPUT
+cat <<EOF >EXPECTED
+id:4EFC743A.3060609@april.org
+id:877h1wv7mg.fsf@inf-8657.int-evry.fr
+id:1258544095-16616-1-git-send-email-chris@chris-wilson.co.uk
+id:877htoqdbo.fsf@yoom.home.cworth.org
+id:878we4qdqf.fsf@yoom.home.cworth.org
+id:87aaykqe24.fsf@yoom.home.cworth.org
+id:87bpj0qeng.fsf@yoom.home.cworth.org
+id:87fx8cqf8v.fsf@yoom.home.cworth.org
+id:87hbssqfix.fsf@yoom.home.cworth.org
+id:87iqd8qgiz.fsf@yoom.home.cworth.org
+id:87k4xoqgnl.fsf@yoom.home.cworth.org
+id:87ocn0qh6d.fsf@yoom.home.cworth.org
+id:87pr7gqidx.fsf@yoom.home.cworth.org
+id:867hto2p0t.fsf@fortitudo.i-did-not-set--mail-host-address--so-tickle-me
+id:1258532999-9316-1-git-send-email-keithp@keithp.com
+id:86aayk2rbj.fsf@fortitudo.i-did-not-set--mail-host-address--so-tickle-me
+id:86d43g2w3y.fsf@fortitudo.i-did-not-set--mail-host-address--so-tickle-me
+id:ddd65cda0911172214t60d22b63hcfeb5a19ab54a39b@mail.gmail.com
+id:86einw2xof.fsf@fortitudo.i-did-not-set--mail-host-address--so-tickle-me
+id:736613.51770.qm@web113505.mail.gq1.yahoo.com
+id:1258520223-15328-1-git-send-email-jan@ryngle.com
+id:ddd65cda0911171950o4eea4389v86de9525e46052d3@mail.gmail.com
+id:1258510940-7018-1-git-send-email-stewart@flamingspork.com
+id:yunzl6kd1w0.fsf@aiko.keithp.com
+id:yun1vjwegii.fsf@aiko.keithp.com
+id:yun3a4cegoa.fsf@aiko.keithp.com
+id:1258509400-32511-1-git-send-email-stewart@flamingspork.com
+id:1258506353-20352-1-git-send-email-stewart@flamingspork.com
+id:20091118010116.GC25380@dottiness.seas.harvard.edu
+id:20091118005829.GB25380@dottiness.seas.harvard.edu
+id:20091118005040.GA25380@dottiness.seas.harvard.edu
+id:cf0c4d610911171623q3e27a0adx802e47039b57604b@mail.gmail.com
+id:1258500222-32066-1-git-send-email-ingmar@exherbo.org
+id:20091117232137.GA7669@griffis1.net
+id:20091118002059.067214ed@hikari
+id:1258498485-sup-142@elly
+id:f35dbb950911171438k5df6eb56k77b6c0944e2e79ae@mail.gmail.com
+id:f35dbb950911171435ieecd458o853c873e35f4be95@mail.gmail.com
+id:1258496327-12086-1-git-send-email-jan@ryngle.com
+id:1258493565-13508-1-git-send-email-keithp@keithp.com
+id:yunaayketfm.fsf@aiko.keithp.com
+id:yunbpj0etua.fsf@aiko.keithp.com
+id:1258491078-29658-1-git-send-email-dottedmag@dottedmag.net
+id:87fx8can9z.fsf@vertex.dottedmag
+id:20091117203301.GV3165@dottiness.seas.harvard.edu
+id:87lji4lx9v.fsf@yoom.home.cworth.org
+id:cf0c4d610911171136h1713aa59w9cf9aa31f052ad0a@mail.gmail.com
+id:87iqd9rn3l.fsf@vertex.dottedmag
+id:20091117190054.GU3165@dottiness.seas.harvard.edu
+id:87lji5cbwo.fsf@yoom.home.cworth.org
+id:1258471718-6781-2-git-send-email-dottedmag@dottedmag.net
+id:1258471718-6781-1-git-send-email-dottedmag@dottedmag.net
+EOF
+test_expect_equal_file OUTPUT EXPECTED
+
+test_begin_subtest "--output=messages --format=json"
+notmuch search --format=json --output=messages '*' >OUTPUT
+cat <<EOF >EXPECTED
+["4EFC743A.3060609@april.org",
+"877h1wv7mg.fsf@inf-8657.int-evry.fr",
+"1258544095-16616-1-git-send-email-chris@chris-wilson.co.uk",
+"877htoqdbo.fsf@yoom.home.cworth.org",
+"878we4qdqf.fsf@yoom.home.cworth.org",
+"87aaykqe24.fsf@yoom.home.cworth.org",
+"87bpj0qeng.fsf@yoom.home.cworth.org",
+"87fx8cqf8v.fsf@yoom.home.cworth.org",
+"87hbssqfix.fsf@yoom.home.cworth.org",
+"87iqd8qgiz.fsf@yoom.home.cworth.org",
+"87k4xoqgnl.fsf@yoom.home.cworth.org",
+"87ocn0qh6d.fsf@yoom.home.cworth.org",
+"87pr7gqidx.fsf@yoom.home.cworth.org",
+"867hto2p0t.fsf@fortitudo.i-did-not-set--mail-host-address--so-tickle-me",
+"1258532999-9316-1-git-send-email-keithp@keithp.com",
+"86aayk2rbj.fsf@fortitudo.i-did-not-set--mail-host-address--so-tickle-me",
+"86d43g2w3y.fsf@fortitudo.i-did-not-set--mail-host-address--so-tickle-me",
+"ddd65cda0911172214t60d22b63hcfeb5a19ab54a39b@mail.gmail.com",
+"86einw2xof.fsf@fortitudo.i-did-not-set--mail-host-address--so-tickle-me",
+"736613.51770.qm@web113505.mail.gq1.yahoo.com",
+"1258520223-15328-1-git-send-email-jan@ryngle.com",
+"ddd65cda0911171950o4eea4389v86de9525e46052d3@mail.gmail.com",
+"1258510940-7018-1-git-send-email-stewart@flamingspork.com",
+"yunzl6kd1w0.fsf@aiko.keithp.com",
+"yun1vjwegii.fsf@aiko.keithp.com",
+"yun3a4cegoa.fsf@aiko.keithp.com",
+"1258509400-32511-1-git-send-email-stewart@flamingspork.com",
+"1258506353-20352-1-git-send-email-stewart@flamingspork.com",
+"20091118010116.GC25380@dottiness.seas.harvard.edu",
+"20091118005829.GB25380@dottiness.seas.harvard.edu",
+"20091118005040.GA25380@dottiness.seas.harvard.edu",
+"cf0c4d610911171623q3e27a0adx802e47039b57604b@mail.gmail.com",
+"1258500222-32066-1-git-send-email-ingmar@exherbo.org",
+"20091117232137.GA7669@griffis1.net",
+"20091118002059.067214ed@hikari",
+"1258498485-sup-142@elly",
+"f35dbb950911171438k5df6eb56k77b6c0944e2e79ae@mail.gmail.com",
+"f35dbb950911171435ieecd458o853c873e35f4be95@mail.gmail.com",
+"1258496327-12086-1-git-send-email-jan@ryngle.com",
+"1258493565-13508-1-git-send-email-keithp@keithp.com",
+"yunaayketfm.fsf@aiko.keithp.com",
+"yunbpj0etua.fsf@aiko.keithp.com",
+"1258491078-29658-1-git-send-email-dottedmag@dottedmag.net",
+"87fx8can9z.fsf@vertex.dottedmag",
+"20091117203301.GV3165@dottiness.seas.harvard.edu",
+"87lji4lx9v.fsf@yoom.home.cworth.org",
+"cf0c4d610911171136h1713aa59w9cf9aa31f052ad0a@mail.gmail.com",
+"87iqd9rn3l.fsf@vertex.dottedmag",
+"20091117190054.GU3165@dottiness.seas.harvard.edu",
+"87lji5cbwo.fsf@yoom.home.cworth.org",
+"1258471718-6781-2-git-send-email-dottedmag@dottedmag.net",
+"1258471718-6781-1-git-send-email-dottedmag@dottedmag.net"]
+EOF
+test_expect_equal_file OUTPUT EXPECTED
+
+test_begin_subtest "--output=files"
+notmuch search --output=files '*' | sed -e "s,$MAIL_DIR,MAIL_DIR," >OUTPUT
+cat <<EOF >EXPECTED
+MAIL_DIR/cur/52:2,
+MAIL_DIR/cur/53:2,
+MAIL_DIR/cur/50:2,
+MAIL_DIR/cur/49:2,
+MAIL_DIR/cur/48:2,
+MAIL_DIR/cur/47:2,
+MAIL_DIR/cur/46:2,
+MAIL_DIR/cur/45:2,
+MAIL_DIR/cur/44:2,
+MAIL_DIR/cur/43:2,
+MAIL_DIR/cur/42:2,
+MAIL_DIR/cur/41:2,
+MAIL_DIR/cur/40:2,
+MAIL_DIR/cur/39:2,
+MAIL_DIR/cur/38:2,
+MAIL_DIR/cur/37:2,
+MAIL_DIR/cur/36:2,
+MAIL_DIR/cur/35:2,
+MAIL_DIR/cur/34:2,
+MAIL_DIR/cur/33:2,
+MAIL_DIR/cur/32:2,
+MAIL_DIR/cur/31:2,
+MAIL_DIR/cur/30:2,
+MAIL_DIR/cur/29:2,
+MAIL_DIR/cur/28:2,
+MAIL_DIR/cur/27:2,
+MAIL_DIR/cur/26:2,
+MAIL_DIR/cur/25:2,
+MAIL_DIR/cur/24:2,
+MAIL_DIR/cur/23:2,
+MAIL_DIR/cur/22:2,
+MAIL_DIR/cur/21:2,
+MAIL_DIR/cur/19:2,
+MAIL_DIR/cur/18:2,
+MAIL_DIR/cur/51:2,
+MAIL_DIR/cur/20:2,
+MAIL_DIR/cur/17:2,
+MAIL_DIR/cur/16:2,
+MAIL_DIR/cur/15:2,
+MAIL_DIR/cur/14:2,
+MAIL_DIR/cur/13:2,
+MAIL_DIR/cur/12:2,
+MAIL_DIR/cur/11:2,
+MAIL_DIR/cur/10:2,
+MAIL_DIR/cur/09:2,
+MAIL_DIR/cur/08:2,
+MAIL_DIR/cur/06:2,
+MAIL_DIR/cur/05:2,
+MAIL_DIR/cur/04:2,
+MAIL_DIR/cur/03:2,
+MAIL_DIR/cur/07:2,
+MAIL_DIR/cur/02:2,
+MAIL_DIR/cur/01:2,
+EOF
+test_expect_equal_file OUTPUT EXPECTED
+
+test_begin_subtest "--output=files --duplicate=1"
+notmuch search --output=files --duplicate=1 '*' | sed -e "s,$MAIL_DIR,MAIL_DIR," >OUTPUT
+cat <<EOF >EXPECTED
+MAIL_DIR/cur/52:2,
+MAIL_DIR/cur/53:2,
+MAIL_DIR/cur/50:2,
+MAIL_DIR/cur/49:2,
+MAIL_DIR/cur/48:2,
+MAIL_DIR/cur/47:2,
+MAIL_DIR/cur/46:2,
+MAIL_DIR/cur/45:2,
+MAIL_DIR/cur/44:2,
+MAIL_DIR/cur/43:2,
+MAIL_DIR/cur/42:2,
+MAIL_DIR/cur/41:2,
+MAIL_DIR/cur/40:2,
+MAIL_DIR/cur/39:2,
+MAIL_DIR/cur/38:2,
+MAIL_DIR/cur/37:2,
+MAIL_DIR/cur/36:2,
+MAIL_DIR/cur/35:2,
+MAIL_DIR/cur/34:2,
+MAIL_DIR/cur/33:2,
+MAIL_DIR/cur/32:2,
+MAIL_DIR/cur/31:2,
+MAIL_DIR/cur/30:2,
+MAIL_DIR/cur/29:2,
+MAIL_DIR/cur/28:2,
+MAIL_DIR/cur/27:2,
+MAIL_DIR/cur/26:2,
+MAIL_DIR/cur/25:2,
+MAIL_DIR/cur/24:2,
+MAIL_DIR/cur/23:2,
+MAIL_DIR/cur/22:2,
+MAIL_DIR/cur/21:2,
+MAIL_DIR/cur/19:2,
+MAIL_DIR/cur/18:2,
+MAIL_DIR/cur/20:2,
+MAIL_DIR/cur/17:2,
+MAIL_DIR/cur/16:2,
+MAIL_DIR/cur/15:2,
+MAIL_DIR/cur/14:2,
+MAIL_DIR/cur/13:2,
+MAIL_DIR/cur/12:2,
+MAIL_DIR/cur/11:2,
+MAIL_DIR/cur/10:2,
+MAIL_DIR/cur/09:2,
+MAIL_DIR/cur/08:2,
+MAIL_DIR/cur/06:2,
+MAIL_DIR/cur/05:2,
+MAIL_DIR/cur/04:2,
+MAIL_DIR/cur/03:2,
+MAIL_DIR/cur/07:2,
+MAIL_DIR/cur/02:2,
+MAIL_DIR/cur/01:2,
+EOF
+test_expect_equal_file OUTPUT EXPECTED
+
+test_begin_subtest "--output=files --format=json"
+notmuch search --format=json --output=files '*' | sed -e "s,$MAIL_DIR,MAIL_DIR," >OUTPUT
+cat <<EOF >EXPECTED
+["MAIL_DIR/cur/52:2,",
+"MAIL_DIR/cur/53:2,",
+"MAIL_DIR/cur/50:2,",
+"MAIL_DIR/cur/49:2,",
+"MAIL_DIR/cur/48:2,",
+"MAIL_DIR/cur/47:2,",
+"MAIL_DIR/cur/46:2,",
+"MAIL_DIR/cur/45:2,",
+"MAIL_DIR/cur/44:2,",
+"MAIL_DIR/cur/43:2,",
+"MAIL_DIR/cur/42:2,",
+"MAIL_DIR/cur/41:2,",
+"MAIL_DIR/cur/40:2,",
+"MAIL_DIR/cur/39:2,",
+"MAIL_DIR/cur/38:2,",
+"MAIL_DIR/cur/37:2,",
+"MAIL_DIR/cur/36:2,",
+"MAIL_DIR/cur/35:2,",
+"MAIL_DIR/cur/34:2,",
+"MAIL_DIR/cur/33:2,",
+"MAIL_DIR/cur/32:2,",
+"MAIL_DIR/cur/31:2,",
+"MAIL_DIR/cur/30:2,",
+"MAIL_DIR/cur/29:2,",
+"MAIL_DIR/cur/28:2,",
+"MAIL_DIR/cur/27:2,",
+"MAIL_DIR/cur/26:2,",
+"MAIL_DIR/cur/25:2,",
+"MAIL_DIR/cur/24:2,",
+"MAIL_DIR/cur/23:2,",
+"MAIL_DIR/cur/22:2,",
+"MAIL_DIR/cur/21:2,",
+"MAIL_DIR/cur/19:2,",
+"MAIL_DIR/cur/18:2,",
+"MAIL_DIR/cur/51:2,",
+"MAIL_DIR/cur/20:2,",
+"MAIL_DIR/cur/17:2,",
+"MAIL_DIR/cur/16:2,",
+"MAIL_DIR/cur/15:2,",
+"MAIL_DIR/cur/14:2,",
+"MAIL_DIR/cur/13:2,",
+"MAIL_DIR/cur/12:2,",
+"MAIL_DIR/cur/11:2,",
+"MAIL_DIR/cur/10:2,",
+"MAIL_DIR/cur/09:2,",
+"MAIL_DIR/cur/08:2,",
+"MAIL_DIR/cur/06:2,",
+"MAIL_DIR/cur/05:2,",
+"MAIL_DIR/cur/04:2,",
+"MAIL_DIR/cur/03:2,",
+"MAIL_DIR/cur/07:2,",
+"MAIL_DIR/cur/02:2,",
+"MAIL_DIR/cur/01:2,"]
+EOF
+test_expect_equal_file OUTPUT EXPECTED
+
+test_begin_subtest "--output=files --format=json --duplicate=2"
+notmuch search --format=json --output=files --duplicate=2 '*' | sed -e "s,$MAIL_DIR,MAIL_DIR," >OUTPUT
+cat <<EOF >EXPECTED
+["MAIL_DIR/cur/51:2,"]
+EOF
+test_expect_equal_file OUTPUT EXPECTED
+
+test_begin_subtest "--output=tags"
+notmuch search --output=tags '*' >OUTPUT
+cat <<EOF >EXPECTED
+attachment
+inbox
+signed
+unread
+EOF
+test_expect_equal_file OUTPUT EXPECTED
+
+test_begin_subtest "--output=tags --format=json"
+notmuch search --format=json --output=tags '*' >OUTPUT
+cat <<EOF >EXPECTED
+["attachment",
+"inbox",
+"signed",
+"unread"]
+EOF
+test_expect_equal_file OUTPUT EXPECTED
+
+test_begin_subtest "sanitize output for quoted-printable line-breaks in author and subject"
+add_message "[subject]='two =?ISO-8859-1?Q?line=0A_subject?=
+ headers'"
+notmuch search id:"$gen_msg_id" | notmuch_search_sanitize >OUTPUT
+cat <<EOF >EXPECTED
+thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; two line? subject headers (inbox unread)
+EOF
+test_expect_equal_file OUTPUT EXPECTED
+
+test_begin_subtest "search for non-existent message prints nothing"
+notmuch search "no-message-matches-this" > OUTPUT
+echo -n >EXPECTED
+test_expect_equal_file OUTPUT EXPECTED
+
+test_begin_subtest "search --format=json for non-existent message prints proper empty json"
+notmuch search --format=json "no-message-matches-this" > OUTPUT
+echo "[]" >EXPECTED
+test_expect_equal_file OUTPUT EXPECTED
+
+test_done
--- /dev/null
+#!/usr/bin/env bash
+test_description='"notmuch search" by folder: (with variations)'
+. ./test-lib.sh
+
+add_message '[dir]=bad' '[subject]="To the bone"'
+add_message '[dir]=bad/news' '[subject]="Bears"'
+mkdir -p "${MAIL_DIR}/duplicate/bad/news"
+cp "$gen_msg_filename" "${MAIL_DIR}/duplicate/bad/news"
+
+add_message '[dir]=things' '[subject]="These are a few"'
+add_message '[dir]=things/favorite' '[subject]="Raindrops, whiskers, kettles"'
+add_message '[dir]=things/bad' '[subject]="Bites, stings, sad feelings"'
+
+test_begin_subtest "Single-world folder: specification (multiple results)"
+output=$(notmuch search folder:bad | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; To the bone (inbox unread)
+thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Bears (inbox unread)
+thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Bites, stings, sad feelings (inbox unread)"
+
+test_begin_subtest "Two-word path to narrow results to one"
+output=$(notmuch search folder:bad/news | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Bears (inbox unread)"
+
+test_begin_subtest "After removing duplicate instance of matching path"
+rm -r "${MAIL_DIR}/bad/news"
+notmuch new
+output=$(notmuch search folder:bad/news | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Bears (inbox unread)"
+
+test_begin_subtest "After rename, old path returns nothing"
+mv "${MAIL_DIR}/duplicate/bad/news" "${MAIL_DIR}/duplicate/bad/olds"
+notmuch new
+output=$(notmuch search folder:bad/news | notmuch_search_sanitize)
+test_expect_equal "$output" ""
+
+test_begin_subtest "After rename, new path returns result"
+output=$(notmuch search folder:bad/olds | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Bears (inbox unread)"
+
+test_done
--- /dev/null
+#!/usr/bin/env bash
+
+# Test to demonstrate a position overlap bug.
+#
+# At one point, notmuch would index terms incorrectly in the case of
+# calling index_terms multiple times for a single field. The term
+# generator was being reset to position 0 each time. This means that
+# with text such as:
+#
+# To: a@b.c, x@y.z
+#
+# one could get a bogus match by searching for:
+#
+# To: a@y.c
+#
+# Thanks to Mark Anderson for reporting the bug, (and providing a nice,
+# minimal test case that inspired what is used here), in
+# id:3wd4o8wa7fx.fsf@testarossa.amd.com
+
+test_description='that notmuch does not overlap term positions'
+. ./test-lib.sh
+
+add_message '[to]="a@b.c, x@y.z"'
+
+test_begin_subtest "Search for a@b.c matches"
+output=$(notmuch search a@b.c | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Test message #1 (inbox unread)"
+
+test_begin_subtest "Search for x@y.z matches"
+output=$(notmuch search x@y.z | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Test message #1 (inbox unread)"
+
+test_begin_subtest "Search for a@y.c must not match"
+output=$(notmuch search a@y.c | notmuch_search_sanitize)
+test_expect_equal "$output" ""
+
+test_done
--- /dev/null
+#!/usr/bin/env bash
+test_description='messages with unquoted . in name'
+. ./test-lib.sh
+
+add_message \
+ '[from]="Some.Name for Someone <bugs@quoting.com>"' \
+ '[subject]="This message needs more quoting on the From line"'
+
+add_message \
+ '[from]="\"Some.Name for Someone\" <bugs@quoting.com>"' \
+ '[subject]="This message has necessary quoting in place"'
+
+add_message \
+ '[from]="No.match Here <filler@mail.com>"' \
+ '[subject]="This message needs more quoting on the From line"'
+
+add_message \
+ '[from]="\"No.match Here\" <filler@mail.com>"' \
+ '[subject]="This message has necessary quoting in place"'
+
+
+test_begin_subtest "Search by first name"
+output=$(notmuch search from:Some.Name | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Some.Name for Someone; This message needs more quoting on the From line (inbox unread)
+thread:XXX 2001-01-05 [1/1] Some.Name for Someone; This message has necessary quoting in place (inbox unread)"
+
+test_begin_subtest "Search by last name:"
+output=$(notmuch search from:Someone | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Some.Name for Someone; This message needs more quoting on the From line (inbox unread)
+thread:XXX 2001-01-05 [1/1] Some.Name for Someone; This message has necessary quoting in place (inbox unread)"
+
+test_begin_subtest "Search by address:"
+output=$(notmuch search from:bugs@quoting.com | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Some.Name for Someone; This message needs more quoting on the From line (inbox unread)
+thread:XXX 2001-01-05 [1/1] Some.Name for Someone; This message has necessary quoting in place (inbox unread)"
+
+test_begin_subtest "Search for all messages:"
+output=$(notmuch search '*' | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Some.Name for Someone; This message needs more quoting on the From line (inbox unread)
+thread:XXX 2001-01-05 [1/1] Some.Name for Someone; This message has necessary quoting in place (inbox unread)
+thread:XXX 2001-01-05 [1/1] No.match Here; This message needs more quoting on the From line (inbox unread)
+thread:XXX 2001-01-05 [1/1] No.match Here; This message has necessary quoting in place (inbox unread)"
+
+test_done
--- /dev/null
+#!/usr/bin/env bash
+test_description='"notmuch search" --offset and --limit parameters'
+. ./test-lib.sh
+
+add_email_corpus
+
+for outp in messages threads; do
+ test_begin_subtest "${outp}: limit does the right thing"
+ notmuch search --output=${outp} "*" | head -n 20 >expected
+ notmuch search --output=${outp} --limit=20 "*" >output
+ test_expect_equal_file expected output
+
+ test_begin_subtest "${outp}: concatenation of limited searches"
+ notmuch search --output=${outp} "*" | head -n 20 >expected
+ notmuch search --output=${outp} --limit=10 "*" >output
+ notmuch search --output=${outp} --limit=10 --offset=10 "*" >>output
+ test_expect_equal_file expected output
+
+ test_begin_subtest "${outp}: limit larger than result set"
+ N=`notmuch count --output=${outp} "*"`
+ notmuch search --output=${outp} "*" >expected
+ notmuch search --output=${outp} --limit=$((1 + ${N})) "*" >output
+ test_expect_equal_file expected output
+
+ test_begin_subtest "${outp}: limit = 0"
+ test_expect_equal "`notmuch search --output=${outp} --limit=0 "*"`" ""
+
+ test_begin_subtest "${outp}: offset does the right thing"
+ # note: tail -n +N is 1-based
+ notmuch search --output=${outp} "*" | tail -n +21 >expected
+ notmuch search --output=${outp} --offset=20 "*" >output
+ test_expect_equal_file expected output
+
+ test_begin_subtest "${outp}: offset = 0"
+ notmuch search --output=${outp} "*" >expected
+ notmuch search --output=${outp} --offset=0 "*" >output
+ test_expect_equal_file expected output
+
+ test_begin_subtest "${outp}: negative offset"
+ notmuch search --output=${outp} "*" | tail -n 20 >expected
+ notmuch search --output=${outp} --offset=-20 "*" >output
+ test_expect_equal_file expected output
+
+ test_begin_subtest "${outp}: negative offset"
+ notmuch search --output=${outp} "*" | tail -n 1 >expected
+ notmuch search --output=${outp} --offset=-1 "*" >output
+ test_expect_equal_file expected output
+
+ test_begin_subtest "${outp}: negative offset combined with limit"
+ notmuch search --output=${outp} "*" | tail -n 20 | head -n 10 >expected
+ notmuch search --output=${outp} --offset=-20 --limit=10 "*" >output
+ test_expect_equal_file expected output
+
+ test_begin_subtest "${outp}: negative offset combined with equal limit"
+ notmuch search --output=${outp} "*" | tail -n 20 >expected
+ notmuch search --output=${outp} --offset=-20 --limit=20 "*" >output
+ test_expect_equal_file expected output
+
+ test_begin_subtest "${outp}: negative offset combined with large limit"
+ notmuch search --output=${outp} "*" | tail -n 20 >expected
+ notmuch search --output=${outp} --offset=-20 --limit=50 "*" >output
+ test_expect_equal_file expected output
+
+ test_begin_subtest "${outp}: negative offset larger then results"
+ N=`notmuch count --output=${outp} "*"`
+ notmuch search --output=${outp} "*" >expected
+ notmuch search --output=${outp} --offset=-$((1 + ${N})) "*" >output
+ test_expect_equal_file expected output
+done
+
+test_done
--- /dev/null
+#!/usr/bin/env bash
+test_description='"notmuch search, count and show" with excludes in several variations'
+. ./test-lib.sh
+
+# Generates a thread consisting of a top level message and 'length'
+# replies. The subject of the top message 'subject: top message"
+# and the subject of the nth reply in the thread is "subject: reply n"
+generate_thread ()
+{
+ local subject="$1"
+ local length="$2"
+ generate_message '[subject]="'"${subject}: top message"'"' '[body]="'"body of top message"'"'
+ parent_id=$gen_msg_id
+ gen_thread_msg_id[0]=$gen_msg_id
+ for i in `seq 1 $length`
+ do
+ generate_message '[subject]="'"${subject}: reply $i"'"' \
+ "[in-reply-to]=\<$parent_id\>" \
+ '[body]="'"body of reply $i"'"'
+ gen_thread_msg_id[$i]=$gen_msg_id
+ parent_id=$gen_msg_id
+ done
+ notmuch new > /dev/null
+ # We cannot retrieve the thread_id until after we have run notmuch new.
+ gen_thread_id=`notmuch search --output=threads id:${gen_thread_msg_id[0]}`
+}
+
+#############################################
+# These are the original search exclude tests.
+
+test_begin_subtest "Search, exclude \"deleted\" messages from search"
+notmuch config set search.exclude_tags deleted
+generate_message '[subject]="Not deleted"'
+not_deleted_id=$gen_msg_id
+generate_message '[subject]="Deleted"'
+notmuch new > /dev/null
+notmuch tag +deleted id:$gen_msg_id
+deleted_id=$gen_msg_id
+output=$(notmuch search subject:deleted | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Not deleted (inbox unread)"
+
+test_begin_subtest "Search, exclude \"deleted\" messages from message search"
+output=$(notmuch search --output=messages subject:deleted | notmuch_search_sanitize)
+test_expect_equal "$output" "id:$not_deleted_id"
+
+test_begin_subtest "Search, exclude \"deleted\" messages from message search --exclude=false"
+output=$(notmuch search --exclude=false --output=messages subject:deleted | notmuch_search_sanitize)
+test_expect_equal "$output" "id:$not_deleted_id
+id:$deleted_id"
+
+test_begin_subtest "Search, exclude \"deleted\" messages from message search (non-existent exclude-tag)"
+notmuch config set search.exclude_tags deleted non_existent_tag
+output=$(notmuch search --output=messages subject:deleted | notmuch_search_sanitize)
+test_expect_equal "$output" "id:$not_deleted_id"
+notmuch config set search.exclude_tags deleted
+
+test_begin_subtest "Search, exclude \"deleted\" messages from search, overridden"
+output=$(notmuch search subject:deleted and tag:deleted | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Deleted (deleted inbox unread)"
+
+test_begin_subtest "Search, exclude \"deleted\" messages from threads"
+add_message '[subject]="Not deleted reply"' '[in-reply-to]="<$gen_msg_id>"'
+output=$(notmuch search subject:deleted | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Not deleted (inbox unread)
+thread:XXX 2001-01-05 [1/2] Notmuch Test Suite; Not deleted reply (deleted inbox unread)"
+
+test_begin_subtest "Search, don't exclude \"deleted\" messages when --exclude=flag specified"
+output=$(notmuch search --exclude=flag subject:deleted | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Not deleted (inbox unread)
+thread:XXX 2001-01-05 [1/2] Notmuch Test Suite; Deleted (deleted inbox unread)"
+
+test_begin_subtest "Search, don't exclude \"deleted\" messages from search if not configured"
+notmuch config set search.exclude_tags
+output=$(notmuch search subject:deleted | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Not deleted (inbox unread)
+thread:XXX 2001-01-05 [2/2] Notmuch Test Suite; Deleted (deleted inbox unread)"
+
+
+########################################################
+# We construct some threads for the tests. We use the tag "test" to
+# indicate which messages we will search for.
+
+# A thread of deleted messages; test matches one of them.
+generate_thread "All messages excluded: single match" 5
+notmuch tag +deleted $gen_thread_id
+notmuch tag +test id:${gen_thread_msg_id[2]}
+
+# A thread of deleted messages; test matches two of them.
+generate_thread "All messages excluded: double match" 5
+notmuch tag +deleted $gen_thread_id
+notmuch tag +test id:${gen_thread_msg_id[2]}
+notmuch tag +test id:${gen_thread_msg_id[4]}
+
+# A thread some messages deleted; test only matches a deleted message.
+generate_thread "Some messages excluded: single excluded match" 5
+notmuch tag +deleted +test id:${gen_thread_msg_id[3]}
+
+# A thread some messages deleted; test only matches a non-deleted message.
+generate_thread "Some messages excluded: single non-excluded match" 5
+notmuch tag +deleted id:${gen_thread_msg_id[2]}
+notmuch tag +test id:${gen_thread_msg_id[4]}
+
+# A thread no messages deleted; test matches a message.
+generate_thread "No messages excluded: single match" 5
+notmuch tag +test id:${gen_thread_msg_id[3]}
+
+# Temporarily remove excludes to get list of matching messages
+notmuch config set search.exclude_tags
+matching_message_ids=( `notmuch search --output=messages tag:test` )
+notmuch config set search.exclude_tags deleted
+
+#########################################
+# Notmuch search tests
+
+test_begin_subtest "Search, default exclusion (thread summary)"
+output=$(notmuch search tag:test | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2001-01-05 [1/6] Notmuch Test Suite; Some messages excluded: single non-excluded match: reply 4 (deleted inbox test unread)
+thread:XXX 2001-01-05 [1/6] Notmuch Test Suite; No messages excluded: single match: reply 3 (inbox test unread)"
+
+test_begin_subtest "Search, default exclusion (messages)"
+output=$(notmuch search --output=messages tag:test | notmuch_search_sanitize)
+test_expect_equal "$output" "${matching_message_ids[4]}
+${matching_message_ids[5]}"
+
+test_begin_subtest "Search, exclude=true (thread summary)"
+output=$(notmuch search --exclude=true tag:test | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2001-01-05 [1/6] Notmuch Test Suite; Some messages excluded: single non-excluded match: reply 4 (deleted inbox test unread)
+thread:XXX 2001-01-05 [1/6] Notmuch Test Suite; No messages excluded: single match: reply 3 (inbox test unread)"
+
+test_begin_subtest "Search, exclude=true (messages)"
+output=$(notmuch search --exclude=true --output=messages tag:test | notmuch_search_sanitize)
+test_expect_equal "$output" "${matching_message_ids[4]}
+${matching_message_ids[5]}"
+
+test_begin_subtest "Search, exclude=false (thread summary)"
+output=$(notmuch search --exclude=false tag:test | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2001-01-05 [1/6] Notmuch Test Suite; All messages excluded: single match: reply 2 (deleted inbox test unread)
+thread:XXX 2001-01-05 [2/6] Notmuch Test Suite; All messages excluded: double match: reply 2 (deleted inbox test unread)
+thread:XXX 2001-01-05 [1/6] Notmuch Test Suite; Some messages excluded: single excluded match: reply 3 (deleted inbox test unread)
+thread:XXX 2001-01-05 [1/6] Notmuch Test Suite; Some messages excluded: single non-excluded match: reply 4 (deleted inbox test unread)
+thread:XXX 2001-01-05 [1/6] Notmuch Test Suite; No messages excluded: single match: reply 3 (inbox test unread)"
+
+test_begin_subtest "Search, exclude=false (messages)"
+output=$(notmuch search --exclude=false --output=messages tag:test | notmuch_search_sanitize)
+test_expect_equal "$output" "${matching_message_ids[0]}
+${matching_message_ids[1]}
+${matching_message_ids[2]}
+${matching_message_ids[3]}
+${matching_message_ids[4]}
+${matching_message_ids[5]}"
+
+test_begin_subtest "Search, exclude=flag (thread summary)"
+output=$(notmuch search --exclude=flag tag:test | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2001-01-05 [0/6] Notmuch Test Suite; All messages excluded: single match: reply 2 (deleted inbox test unread)
+thread:XXX 2001-01-05 [0/6] Notmuch Test Suite; All messages excluded: double match: reply 2 (deleted inbox test unread)
+thread:XXX 2001-01-05 [0/6] Notmuch Test Suite; Some messages excluded: single excluded match: reply 3 (deleted inbox test unread)
+thread:XXX 2001-01-05 [1/6] Notmuch Test Suite; Some messages excluded: single non-excluded match: reply 4 (deleted inbox test unread)
+thread:XXX 2001-01-05 [1/6] Notmuch Test Suite; No messages excluded: single match: reply 3 (inbox test unread)"
+
+test_begin_subtest "Search, exclude=flag (messages)"
+output=$(notmuch search --exclude=flag --output=messages tag:test | notmuch_search_sanitize)
+test_expect_equal "$output" "${matching_message_ids[0]}
+${matching_message_ids[1]}
+${matching_message_ids[2]}
+${matching_message_ids[3]}
+${matching_message_ids[4]}
+${matching_message_ids[5]}"
+
+test_begin_subtest "Search, exclude=all (thread summary)"
+output=$(notmuch search --exclude=all tag:test | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2001-01-05 [1/5] Notmuch Test Suite; Some messages excluded: single non-excluded match: reply 4 (inbox test unread)
+thread:XXX 2001-01-05 [1/6] Notmuch Test Suite; No messages excluded: single match: reply 3 (inbox test unread)"
+
+test_begin_subtest "Search, exclude=all (messages)"
+output=$(notmuch search --exclude=all --output=messages tag:test | notmuch_search_sanitize)
+test_expect_equal "$output" "${matching_message_ids[4]}
+${matching_message_ids[5]}"
+
+test_begin_subtest "Search, default exclusion: tag in query (thread summary)"
+output=$(notmuch search tag:test and tag:deleted | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2001-01-05 [1/6] Notmuch Test Suite; All messages excluded: single match: reply 2 (deleted inbox test unread)
+thread:XXX 2001-01-05 [2/6] Notmuch Test Suite; All messages excluded: double match: reply 2 (deleted inbox test unread)
+thread:XXX 2001-01-05 [1/6] Notmuch Test Suite; Some messages excluded: single excluded match: reply 3 (deleted inbox test unread)"
+
+test_begin_subtest "Search, default exclusion: tag in query (messages)"
+output=$(notmuch search --output=messages tag:test and tag:deleted | notmuch_search_sanitize)
+test_expect_equal "$output" "${matching_message_ids[0]}
+${matching_message_ids[1]}
+${matching_message_ids[2]}
+${matching_message_ids[3]}"
+
+test_begin_subtest "Search, exclude=true: tag in query (thread summary)"
+output=$(notmuch search --exclude=true tag:test and tag:deleted | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2001-01-05 [1/6] Notmuch Test Suite; All messages excluded: single match: reply 2 (deleted inbox test unread)
+thread:XXX 2001-01-05 [2/6] Notmuch Test Suite; All messages excluded: double match: reply 2 (deleted inbox test unread)
+thread:XXX 2001-01-05 [1/6] Notmuch Test Suite; Some messages excluded: single excluded match: reply 3 (deleted inbox test unread)"
+
+test_begin_subtest "Search, exclude=true: tag in query (messages)"
+output=$(notmuch search --exclude=true --output=messages tag:test and tag:deleted | notmuch_search_sanitize)
+test_expect_equal "$output" "${matching_message_ids[0]}
+${matching_message_ids[1]}
+${matching_message_ids[2]}
+${matching_message_ids[3]}"
+
+test_begin_subtest "Search, exclude=false: tag in query (thread summary)"
+output=$(notmuch search --exclude=false tag:test and tag:deleted | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2001-01-05 [1/6] Notmuch Test Suite; All messages excluded: single match: reply 2 (deleted inbox test unread)
+thread:XXX 2001-01-05 [2/6] Notmuch Test Suite; All messages excluded: double match: reply 2 (deleted inbox test unread)
+thread:XXX 2001-01-05 [1/6] Notmuch Test Suite; Some messages excluded: single excluded match: reply 3 (deleted inbox test unread)"
+
+test_begin_subtest "Search, exclude=false: tag in query (messages)"
+output=$(notmuch search --exclude=false --output=messages tag:test and tag:deleted | notmuch_search_sanitize)
+test_expect_equal "$output" "${matching_message_ids[0]}
+${matching_message_ids[1]}
+${matching_message_ids[2]}
+${matching_message_ids[3]}"
+
+test_begin_subtest "Search, exclude=flag: tag in query (thread summary)"
+output=$(notmuch search --exclude=flag tag:test and tag:deleted | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2001-01-05 [1/6] Notmuch Test Suite; All messages excluded: single match: reply 2 (deleted inbox test unread)
+thread:XXX 2001-01-05 [2/6] Notmuch Test Suite; All messages excluded: double match: reply 2 (deleted inbox test unread)
+thread:XXX 2001-01-05 [1/6] Notmuch Test Suite; Some messages excluded: single excluded match: reply 3 (deleted inbox test unread)"
+
+test_begin_subtest "Search, exclude=flag: tag in query (messages)"
+output=$(notmuch search --exclude=flag --output=messages tag:test and tag:deleted | notmuch_search_sanitize)
+test_expect_equal "$output" "${matching_message_ids[0]}
+${matching_message_ids[1]}
+${matching_message_ids[2]}
+${matching_message_ids[3]}"
+
+test_begin_subtest "Search, exclude=all: tag in query (thread summary)"
+output=$(notmuch search --exclude=all tag:test and tag:deleted | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2001-01-05 [1/6] Notmuch Test Suite; All messages excluded: single match: reply 2 (deleted inbox test unread)
+thread:XXX 2001-01-05 [2/6] Notmuch Test Suite; All messages excluded: double match: reply 2 (deleted inbox test unread)
+thread:XXX 2001-01-05 [1/6] Notmuch Test Suite; Some messages excluded: single excluded match: reply 3 (deleted inbox test unread)"
+
+test_begin_subtest "Search, exclude=all: tag in query (messages)"
+output=$(notmuch search --exclude=all --output=messages tag:test and tag:deleted | notmuch_search_sanitize)
+test_expect_equal "$output" "${matching_message_ids[0]}
+${matching_message_ids[1]}
+${matching_message_ids[2]}
+${matching_message_ids[3]}"
+
+#########################################################
+# Notmuch count tests
+
+test_begin_subtest "Count, default exclusion (messages)"
+output=$(notmuch count tag:test)
+test_expect_equal "$output" "2"
+
+test_begin_subtest "Count, default exclusion (threads)"
+output=$(notmuch count --output=threads tag:test)
+test_expect_equal "$output" "2"
+
+test_begin_subtest "Count, exclude=true (messages)"
+output=$(notmuch count --exclude=true tag:test)
+test_expect_equal "$output" "2"
+
+test_begin_subtest "Count, exclude=true (threads)"
+output=$(notmuch count --output=threads --exclude=true tag:test)
+test_expect_equal "$output" "2"
+
+test_begin_subtest "Count, exclude=false (messages)"
+output=$(notmuch count --exclude=false tag:test)
+test_expect_equal "$output" "6"
+
+test_begin_subtest "Count, exclude=false (threads)"
+output=$(notmuch count --output=threads --exclude=false tag:test)
+test_expect_equal "$output" "5"
+
+test_begin_subtest "Count, default exclusion: tag in query (messages)"
+output=$(notmuch count tag:test and tag:deleted)
+test_expect_equal "$output" "4"
+
+test_begin_subtest "Count, default exclusion: tag in query (threads)"
+output=$(notmuch count --output=threads tag:test and tag:deleted)
+test_expect_equal "$output" "3"
+
+test_begin_subtest "Count, exclude=true: tag in query (messages)"
+output=$(notmuch count --exclude=true tag:test and tag:deleted)
+test_expect_equal "$output" "4"
+
+test_begin_subtest "Count, exclude=true: tag in query (threads)"
+output=$(notmuch count --output=threads --exclude=true tag:test and tag:deleted)
+test_expect_equal "$output" "3"
+
+test_begin_subtest "Count, exclude=false: tag in query (messages)"
+output=$(notmuch count --exclude=false tag:test and tag:deleted)
+test_expect_equal "$output" "4"
+
+test_begin_subtest "Count, exclude=false: tag in query (threads)"
+output=$(notmuch count --output=threads --exclude=false tag:test and tag:deleted)
+test_expect_equal "$output" "3"
+
+#############################################################
+# Show tests
+
+test_begin_subtest "Show, default exclusion"
+output=$(notmuch show tag:test | notmuch_show_sanitize_all | egrep "Subject:|message{")
+test_expect_equal "$output" "\fmessage{ id:XXXXX depth:0 match:1 excluded:0 filename:XXXXX
+Subject: Some messages excluded: single non-excluded match: reply 4
+\fmessage{ id:XXXXX depth:0 match:1 excluded:0 filename:XXXXX
+Subject: No messages excluded: single match: reply 3"
+
+test_begin_subtest "Show, default exclusion (entire-thread)"
+output=$(notmuch show --entire-thread tag:test | notmuch_show_sanitize_all | egrep "Subject:|message{")
+test_expect_equal "$output" "\fmessage{ id:XXXXX depth:0 match:0 excluded:0 filename:XXXXX
+Subject: Some messages excluded: single non-excluded match: top message
+\fmessage{ id:XXXXX depth:1 match:0 excluded:0 filename:XXXXX
+Subject: Some messages excluded: single non-excluded match: reply 1
+\fmessage{ id:XXXXX depth:2 match:0 excluded:1 filename:XXXXX
+Subject: Some messages excluded: single non-excluded match: reply 2
+\fmessage{ id:XXXXX depth:3 match:0 excluded:0 filename:XXXXX
+Subject: Some messages excluded: single non-excluded match: reply 3
+\fmessage{ id:XXXXX depth:4 match:1 excluded:0 filename:XXXXX
+Subject: Some messages excluded: single non-excluded match: reply 4
+\fmessage{ id:XXXXX depth:5 match:0 excluded:0 filename:XXXXX
+Subject: Some messages excluded: single non-excluded match: reply 5
+\fmessage{ id:XXXXX depth:0 match:0 excluded:0 filename:XXXXX
+Subject: No messages excluded: single match: top message
+\fmessage{ id:XXXXX depth:1 match:0 excluded:0 filename:XXXXX
+Subject: No messages excluded: single match: reply 1
+\fmessage{ id:XXXXX depth:2 match:0 excluded:0 filename:XXXXX
+Subject: No messages excluded: single match: reply 2
+\fmessage{ id:XXXXX depth:3 match:1 excluded:0 filename:XXXXX
+Subject: No messages excluded: single match: reply 3
+\fmessage{ id:XXXXX depth:4 match:0 excluded:0 filename:XXXXX
+Subject: No messages excluded: single match: reply 4
+\fmessage{ id:XXXXX depth:5 match:0 excluded:0 filename:XXXXX
+Subject: No messages excluded: single match: reply 5"
+
+test_begin_subtest "Show, exclude=true"
+output=$(notmuch show --exclude=true tag:test | notmuch_show_sanitize_all | egrep "Subject:|message{")
+test_expect_equal "$output" "\fmessage{ id:XXXXX depth:0 match:1 excluded:0 filename:XXXXX
+Subject: Some messages excluded: single non-excluded match: reply 4
+\fmessage{ id:XXXXX depth:0 match:1 excluded:0 filename:XXXXX
+Subject: No messages excluded: single match: reply 3"
+
+test_begin_subtest "Show, exclude=true (entire-thread)"
+output=$(notmuch show --entire-thread --exclude=true tag:test | notmuch_show_sanitize_all | egrep "Subject:|message{")
+test_expect_equal "$output" "\fmessage{ id:XXXXX depth:0 match:0 excluded:0 filename:XXXXX
+Subject: Some messages excluded: single non-excluded match: top message
+\fmessage{ id:XXXXX depth:1 match:0 excluded:0 filename:XXXXX
+Subject: Some messages excluded: single non-excluded match: reply 1
+\fmessage{ id:XXXXX depth:2 match:0 excluded:1 filename:XXXXX
+Subject: Some messages excluded: single non-excluded match: reply 2
+\fmessage{ id:XXXXX depth:3 match:0 excluded:0 filename:XXXXX
+Subject: Some messages excluded: single non-excluded match: reply 3
+\fmessage{ id:XXXXX depth:4 match:1 excluded:0 filename:XXXXX
+Subject: Some messages excluded: single non-excluded match: reply 4
+\fmessage{ id:XXXXX depth:5 match:0 excluded:0 filename:XXXXX
+Subject: Some messages excluded: single non-excluded match: reply 5
+\fmessage{ id:XXXXX depth:0 match:0 excluded:0 filename:XXXXX
+Subject: No messages excluded: single match: top message
+\fmessage{ id:XXXXX depth:1 match:0 excluded:0 filename:XXXXX
+Subject: No messages excluded: single match: reply 1
+\fmessage{ id:XXXXX depth:2 match:0 excluded:0 filename:XXXXX
+Subject: No messages excluded: single match: reply 2
+\fmessage{ id:XXXXX depth:3 match:1 excluded:0 filename:XXXXX
+Subject: No messages excluded: single match: reply 3
+\fmessage{ id:XXXXX depth:4 match:0 excluded:0 filename:XXXXX
+Subject: No messages excluded: single match: reply 4
+\fmessage{ id:XXXXX depth:5 match:0 excluded:0 filename:XXXXX
+Subject: No messages excluded: single match: reply 5"
+
+test_begin_subtest "Show, exclude=false"
+output=$(notmuch show --exclude=false tag:test | notmuch_show_sanitize_all | egrep "Subject:|message{")
+test_expect_equal "$output" "\fmessage{ id:XXXXX depth:0 match:1 excluded:1 filename:XXXXX
+Subject: All messages excluded: single match: reply 2
+\fmessage{ id:XXXXX depth:0 match:1 excluded:1 filename:XXXXX
+Subject: All messages excluded: double match: reply 2
+\fmessage{ id:XXXXX depth:1 match:1 excluded:1 filename:XXXXX
+Subject: All messages excluded: double match: reply 4
+\fmessage{ id:XXXXX depth:0 match:1 excluded:1 filename:XXXXX
+Subject: Some messages excluded: single excluded match: reply 3
+\fmessage{ id:XXXXX depth:0 match:1 excluded:0 filename:XXXXX
+Subject: Some messages excluded: single non-excluded match: reply 4
+\fmessage{ id:XXXXX depth:0 match:1 excluded:0 filename:XXXXX
+Subject: No messages excluded: single match: reply 3"
+
+test_begin_subtest "Show, exclude=false (entire-thread)"
+output=$(notmuch show --entire-thread --exclude=false tag:test | notmuch_show_sanitize_all | egrep "Subject:|message{")
+test_expect_equal "$output" "\fmessage{ id:XXXXX depth:0 match:0 excluded:1 filename:XXXXX
+Subject: All messages excluded: single match: top message
+\fmessage{ id:XXXXX depth:1 match:0 excluded:1 filename:XXXXX
+Subject: All messages excluded: single match: reply 1
+\fmessage{ id:XXXXX depth:2 match:1 excluded:1 filename:XXXXX
+Subject: All messages excluded: single match: reply 2
+\fmessage{ id:XXXXX depth:3 match:0 excluded:1 filename:XXXXX
+Subject: All messages excluded: single match: reply 3
+\fmessage{ id:XXXXX depth:4 match:0 excluded:1 filename:XXXXX
+Subject: All messages excluded: single match: reply 4
+\fmessage{ id:XXXXX depth:5 match:0 excluded:1 filename:XXXXX
+Subject: All messages excluded: single match: reply 5
+\fmessage{ id:XXXXX depth:0 match:0 excluded:1 filename:XXXXX
+Subject: All messages excluded: double match: top message
+\fmessage{ id:XXXXX depth:1 match:0 excluded:1 filename:XXXXX
+Subject: All messages excluded: double match: reply 1
+\fmessage{ id:XXXXX depth:2 match:1 excluded:1 filename:XXXXX
+Subject: All messages excluded: double match: reply 2
+\fmessage{ id:XXXXX depth:3 match:0 excluded:1 filename:XXXXX
+Subject: All messages excluded: double match: reply 3
+\fmessage{ id:XXXXX depth:4 match:1 excluded:1 filename:XXXXX
+Subject: All messages excluded: double match: reply 4
+\fmessage{ id:XXXXX depth:5 match:0 excluded:1 filename:XXXXX
+Subject: All messages excluded: double match: reply 5
+\fmessage{ id:XXXXX depth:0 match:0 excluded:0 filename:XXXXX
+Subject: Some messages excluded: single excluded match: top message
+\fmessage{ id:XXXXX depth:1 match:0 excluded:0 filename:XXXXX
+Subject: Some messages excluded: single excluded match: reply 1
+\fmessage{ id:XXXXX depth:2 match:0 excluded:0 filename:XXXXX
+Subject: Some messages excluded: single excluded match: reply 2
+\fmessage{ id:XXXXX depth:3 match:1 excluded:1 filename:XXXXX
+Subject: Some messages excluded: single excluded match: reply 3
+\fmessage{ id:XXXXX depth:4 match:0 excluded:0 filename:XXXXX
+Subject: Some messages excluded: single excluded match: reply 4
+\fmessage{ id:XXXXX depth:5 match:0 excluded:0 filename:XXXXX
+Subject: Some messages excluded: single excluded match: reply 5
+\fmessage{ id:XXXXX depth:0 match:0 excluded:0 filename:XXXXX
+Subject: Some messages excluded: single non-excluded match: top message
+\fmessage{ id:XXXXX depth:1 match:0 excluded:0 filename:XXXXX
+Subject: Some messages excluded: single non-excluded match: reply 1
+\fmessage{ id:XXXXX depth:2 match:0 excluded:1 filename:XXXXX
+Subject: Some messages excluded: single non-excluded match: reply 2
+\fmessage{ id:XXXXX depth:3 match:0 excluded:0 filename:XXXXX
+Subject: Some messages excluded: single non-excluded match: reply 3
+\fmessage{ id:XXXXX depth:4 match:1 excluded:0 filename:XXXXX
+Subject: Some messages excluded: single non-excluded match: reply 4
+\fmessage{ id:XXXXX depth:5 match:0 excluded:0 filename:XXXXX
+Subject: Some messages excluded: single non-excluded match: reply 5
+\fmessage{ id:XXXXX depth:0 match:0 excluded:0 filename:XXXXX
+Subject: No messages excluded: single match: top message
+\fmessage{ id:XXXXX depth:1 match:0 excluded:0 filename:XXXXX
+Subject: No messages excluded: single match: reply 1
+\fmessage{ id:XXXXX depth:2 match:0 excluded:0 filename:XXXXX
+Subject: No messages excluded: single match: reply 2
+\fmessage{ id:XXXXX depth:3 match:1 excluded:0 filename:XXXXX
+Subject: No messages excluded: single match: reply 3
+\fmessage{ id:XXXXX depth:4 match:0 excluded:0 filename:XXXXX
+Subject: No messages excluded: single match: reply 4
+\fmessage{ id:XXXXX depth:5 match:0 excluded:0 filename:XXXXX
+Subject: No messages excluded: single match: reply 5"
+
+
+test_done
--- /dev/null
+#!/usr/bin/env bash
+test_description='"notmuch tag"'
+. ./test-lib.sh
+
+add_message '[subject]=One'
+add_message '[subject]=Two'
+
+test_begin_subtest "Adding tags"
+notmuch tag +tag1 +tag2 +tag3 \*
+output=$(notmuch search \* | notmuch_search_sanitize)
+test_expect_equal "$output" "\
+thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; One (inbox tag1 tag2 tag3 unread)
+thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Two (inbox tag1 tag2 tag3 unread)"
+
+test_begin_subtest "Removing tags"
+notmuch tag -tag1 -tag2 \*
+output=$(notmuch search \* | notmuch_search_sanitize)
+test_expect_equal "$output" "\
+thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; One (inbox tag3 unread)
+thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Two (inbox tag3 unread)"
+
+test_expect_code 1 "No tag operations" 'notmuch tag One'
+test_expect_code 1 "No query" 'notmuch tag +tag2'
+
+test_begin_subtest "Redundant tagging"
+notmuch tag +tag1 -tag3 One
+notmuch tag +tag1 -tag3 \*
+output=$(notmuch search \* | notmuch_search_sanitize)
+test_expect_equal "$output" "\
+thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; One (inbox tag1 unread)
+thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Two (inbox tag1 unread)"
+
+test_begin_subtest "Remove all"
+notmuch tag --remove-all One
+notmuch tag --remove-all +tag5 +tag6 +unread Two
+output=$(notmuch search \* | notmuch_search_sanitize)
+test_expect_equal "$output" "\
+thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; One ()
+thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Two (tag5 tag6 unread)"
+
+test_begin_subtest "Remove all with a no-op"
+notmuch tag +inbox +tag1 +unread One
+notmuch tag --remove-all +foo +inbox +tag1 -foo +unread Two
+output=$(notmuch search \* | notmuch_search_sanitize)
+test_expect_equal "$output" "\
+thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; One (inbox tag1 unread)
+thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Two (inbox tag1 unread)"
+
+test_begin_subtest "Special characters in tags"
+notmuch tag +':" ' \*
+notmuch tag -':" ' Two
+output=$(notmuch search \* | notmuch_search_sanitize)
+test_expect_equal "$output" "\
+thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; One (:\" inbox tag1 unread)
+thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Two (inbox tag1 unread)"
+
+test_begin_subtest "Tagging order"
+notmuch tag +tag4 -tag4 One
+notmuch tag -tag4 +tag4 Two
+output=$(notmuch search \* | notmuch_search_sanitize)
+test_expect_equal "$output" "\
+thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; One (:\" inbox tag1 unread)
+thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Two (inbox tag1 tag4 unread)"
+
+test_begin_subtest "--batch"
+notmuch tag --batch <<EOF
+# %20 is a space in tag
+-:"%20 -tag1 +tag5 +tag6 -- One
++tag1 -tag1 -tag4 +tag4 -- Two
+-tag6 One
++tag5 Two
+EOF
+output=$(notmuch search \* | notmuch_search_sanitize)
+test_expect_equal "$output" "\
+thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; One (inbox tag5 unread)
+thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Two (inbox tag4 tag5 unread)"
+
+# generate a common input file for the next several tests.
+cat > batch.in <<EOF
+# %40 is an @ in tag
++%40 -tag5 +tag6 -- One
++tag1 -tag1 -tag4 +tag4 -- Two
+-tag5 +tag6 Two
+EOF
+
+cat > batch.expected <<EOF
+thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; One (@ inbox tag6 unread)
+thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Two (inbox tag4 tag6 unread)
+EOF
+
+test_begin_subtest "--input"
+notmuch dump --format=batch-tag > backup.tags
+notmuch tag --input=batch.in
+notmuch search \* | notmuch_search_sanitize > OUTPUT
+notmuch restore --format=batch-tag < backup.tags
+test_expect_equal_file batch.expected OUTPUT
+
+test_begin_subtest "--batch --input"
+notmuch dump --format=batch-tag > backup.tags
+notmuch tag --batch --input=batch.in
+notmuch search \* | notmuch_search_sanitize > OUTPUT
+notmuch restore --format=batch-tag < backup.tags
+test_expect_equal_file batch.expected OUTPUT
+
+test_begin_subtest "--batch, blank lines and comments"
+notmuch dump | sort > EXPECTED
+notmuch tag --batch <<EOF
+# this line is a comment; the next has only white space
+
+
+# the previous line is empty
+EOF
+notmuch dump | sort > OUTPUT
+test_expect_equal_file EXPECTED OUTPUT
+
+test_begin_subtest '--batch: checking error messages'
+notmuch dump --format=batch-tag > BACKUP
+notmuch tag --batch <<EOF 2>OUTPUT
+# the next line has a space
+
+# this line has no tag operations, but this is permitted in batch format.
+a
++0
++a +b
+# trailing whitespace
++a +b
++c +d --
+# this is a harmless comment, do not yell about it.
+
+# the previous line was blank; also no yelling please
++%zz -- id:whatever
+# the next non-comment line should report an an empty tag error for
+# batch tagging, but not for restore
++ +e -- id:foo
++- -- id:foo
+EOF
+
+cat <<EOF > EXPECTED
+Warning: no query string [+0]
+Warning: no query string [+a +b]
+Warning: missing query string [+a +b ]
+Warning: no query string after -- [+c +d --]
+Warning: hex decoding of tag %zz failed [+%zz -- id:whatever]
+Warning: empty tag forbidden [+ +e -- id:foo]
+Warning: tag starting with '-' forbidden [+- -- id:foo]
+EOF
+
+notmuch restore --format=batch-tag < BACKUP
+test_expect_equal_file EXPECTED OUTPUT
+
+test_begin_subtest '--batch: tags with quotes'
+notmuch dump --format=batch-tag > BACKUP
+
+notmuch tag --batch <<EOF
++%22%27%22%27%22%22%27%27 -- One
+-%22%27%22%27%22%22%27%27 -- One
++%22%27%22%22%22%27 -- One
++%22%27%22%27%22%22%27%27 -- Two
+EOF
+
+cat <<EOF > EXPECTED
++%22%27%22%22%22%27 +inbox +tag5 +unread -- id:msg-001@notmuch-test-suite
++%22%27%22%27%22%22%27%27 +inbox +tag4 +tag5 +unread -- id:msg-002@notmuch-test-suite
+EOF
+
+notmuch dump --format=batch-tag | sort > OUTPUT
+notmuch restore --format=batch-tag < BACKUP
+test_expect_equal_file EXPECTED OUTPUT
+
+test_begin_subtest '--batch: tags with punctuation and space'
+notmuch dump --format=batch-tag > BACKUP
+
+notmuch tag --batch <<EOF
++%21@%23%24%25%5e%26%2a%29-_=+%5b%7b%5c%20%7c%3b%3a%27%20%22,.%3c%60%7e -- One
+-%21@%23%24%25%5e%26%2a%29-_=+%5b%7b%5c%20%7c%3b%3a%27%20%22,.%3c%60%7e -- One
++%21@%23%24%25%5e%26%2a%29-_=+%5b%7b%5c%20%7c%3b%3a%27%20%22,.%3c%20%60%7e -- Two
+-%21@%23%24%25%5e%26%2a%29-_=+%5b%7b%5c%20%7c%3b%3a%27%20%22,.%3c%20%60%7e -- Two
++%21@%23%20%24%25%5e%26%2a%29-_=+%5b%7b%5c%20%7c%3b%3a%27%20%22,.%3c%60%7e -- One
++%21@%23%20%24%25%5e%26%2a%29-_=+%5b%7b%5c%20%7c%3b%3a%27%20%22,.%3c%60%7e -- Two
+EOF
+
+cat <<EOF > EXPECTED
++%21@%23%20%24%25%5e%26%2a%29-_=+%5b%7b%5c%20%7c%3b%3a%27%20%22,.%3c%60%7e +inbox +tag4 +tag5 +unread -- id:msg-002@notmuch-test-suite
++%21@%23%20%24%25%5e%26%2a%29-_=+%5b%7b%5c%20%7c%3b%3a%27%20%22,.%3c%60%7e +inbox +tag5 +unread -- id:msg-001@notmuch-test-suite
+EOF
+
+notmuch dump --format=batch-tag | sort > OUTPUT
+notmuch restore --format=batch-tag < BACKUP
+test_expect_equal_file EXPECTED OUTPUT
+
+test_begin_subtest '--batch: unicode tags'
+notmuch dump --format=batch-tag > BACKUP
+
+notmuch tag --batch <<EOF
++%2a@%7d%cf%b5%f4%85%80%adO3%da%a7 -- One
++=%e0%ac%95%c8%b3+%ef%aa%95%c8%a64w%c7%9d%c9%a2%cf%b3%d6%82%24B%c4%a9%c5%a1UX%ee%99%b0%27E7%ca%a4%d0%8b%5d -- One
++A%e1%a0%bc%de%8b%d5%b2V%d9%9b%f3%b5%a2%a3M%d8%a1u@%f0%a0%ac%948%7e%f0%ab%86%af%27 -- One
++R -- One
++%da%88=f%cc%b9I%ce%af%7b%c9%97%e3%b9%8bH%cb%92X%d2%8c6 -- One
++%dc%9crh%d2%86B%e5%97%a2%22t%ed%99%82d -- One
++L%df%85%ef%a1%a5m@%d3%96%c2%ab%d4%9f%ca%b8%f3%b3%a2%bf%c7%b1_u%d7%b4%c7%b1 -- One
++P%c4%98%2f -- One
++%7e%d1%8b%25%ec%a0%ae%d1%a0M%3b%e3%b6%b7%e9%a4%87%3c%db%9a%cc%a8%e1%96%9d -- One
++%c4%bf7%c7%ab9H%c4%99k%ea%91%bd%c3%8ck%e2%b3%8dk%c5%952V%e4%99%b2%d9%b3%e4%8b%bda%5b%24%c7%9b -- One
++%2a@%7d%cf%b5%f4%85%80%adO3%da%a7 +=%e0%ac%95%c8%b3+%ef%aa%95%c8%a64w%c7%9d%c9%a2%cf%b3%d6%82%24B%c4%a9%c5%a1UX%ee%99%b0%27E7%ca%a4%d0%8b%5d +A%e1%a0%bc%de%8b%d5%b2V%d9%9b%f3%b5%a2%a3M%d8%a1u@%f0%a0%ac%948%7e%f0%ab%86%af%27 +R +%da%88=f%cc%b9I%ce%af%7b%c9%97%e3%b9%8bH%cb%92X%d2%8c6 +%dc%9crh%d2%86B%e5%97%a2%22t%ed%99%82d +L%df%85%ef%a1%a5m@%d3%96%c2%ab%d4%9f%ca%b8%f3%b3%a2%bf%c7%b1_u%d7%b4%c7%b1 +P%c4%98%2f +%7e%d1%8b%25%ec%a0%ae%d1%a0M%3b%e3%b6%b7%e9%a4%87%3c%db%9a%cc%a8%e1%96%9d +%c4%bf7%c7%ab9H%c4%99k%ea%91%bd%c3%8ck%e2%b3%8dk%c5%952V%e4%99%b2%d9%b3%e4%8b%bda%5b%24%c7%9b -- Two
+EOF
+
+cat <<EOF > EXPECTED
++%2a@%7d%cf%b5%f4%85%80%adO3%da%a7 +=%e0%ac%95%c8%b3+%ef%aa%95%c8%a64w%c7%9d%c9%a2%cf%b3%d6%82%24B%c4%a9%c5%a1UX%ee%99%b0%27E7%ca%a4%d0%8b%5d +A%e1%a0%bc%de%8b%d5%b2V%d9%9b%f3%b5%a2%a3M%d8%a1u@%f0%a0%ac%948%7e%f0%ab%86%af%27 +L%df%85%ef%a1%a5m@%d3%96%c2%ab%d4%9f%ca%b8%f3%b3%a2%bf%c7%b1_u%d7%b4%c7%b1 +P%c4%98%2f +R +inbox +tag4 +tag5 +unread +%7e%d1%8b%25%ec%a0%ae%d1%a0M%3b%e3%b6%b7%e9%a4%87%3c%db%9a%cc%a8%e1%96%9d +%c4%bf7%c7%ab9H%c4%99k%ea%91%bd%c3%8ck%e2%b3%8dk%c5%952V%e4%99%b2%d9%b3%e4%8b%bda%5b%24%c7%9b +%da%88=f%cc%b9I%ce%af%7b%c9%97%e3%b9%8bH%cb%92X%d2%8c6 +%dc%9crh%d2%86B%e5%97%a2%22t%ed%99%82d -- id:msg-002@notmuch-test-suite
++%2a@%7d%cf%b5%f4%85%80%adO3%da%a7 +=%e0%ac%95%c8%b3+%ef%aa%95%c8%a64w%c7%9d%c9%a2%cf%b3%d6%82%24B%c4%a9%c5%a1UX%ee%99%b0%27E7%ca%a4%d0%8b%5d +A%e1%a0%bc%de%8b%d5%b2V%d9%9b%f3%b5%a2%a3M%d8%a1u@%f0%a0%ac%948%7e%f0%ab%86%af%27 +L%df%85%ef%a1%a5m@%d3%96%c2%ab%d4%9f%ca%b8%f3%b3%a2%bf%c7%b1_u%d7%b4%c7%b1 +P%c4%98%2f +R +inbox +tag5 +unread +%7e%d1%8b%25%ec%a0%ae%d1%a0M%3b%e3%b6%b7%e9%a4%87%3c%db%9a%cc%a8%e1%96%9d +%c4%bf7%c7%ab9H%c4%99k%ea%91%bd%c3%8ck%e2%b3%8dk%c5%952V%e4%99%b2%d9%b3%e4%8b%bda%5b%24%c7%9b +%da%88=f%cc%b9I%ce%af%7b%c9%97%e3%b9%8bH%cb%92X%d2%8c6 +%dc%9crh%d2%86B%e5%97%a2%22t%ed%99%82d -- id:msg-001@notmuch-test-suite
+EOF
+
+notmuch dump --format=batch-tag | sort > OUTPUT
+notmuch restore --format=batch-tag < BACKUP
+test_expect_equal_file EXPECTED OUTPUT
+
+test_begin_subtest "--batch: only space and % needs to be encoded."
+notmuch dump --format=batch-tag > BACKUP
+
+notmuch tag --batch <<EOF
++winner *
++foo::bar%25 -- (One and Two) or (One and tag:winner)
++found::it -- tag:foo::bar%
+# ignore this line and the next
+
++space%20in%20tags -- Two
+# add tag '(tags)', among other stunts.
++crazy{ +(tags) +&are +#possible\ -- tag:"space in tags"
++match*crazy -- tag:crazy{
++some_tag -- id:"this is ""nauty)"""
+EOF
+
+cat <<EOF > EXPECTED
++%23possible%5c +%26are +%28tags%29 +crazy%7b +inbox +match%2acrazy +space%20in%20tags +tag4 +tag5 +unread +winner -- id:msg-002@notmuch-test-suite
++foo%3a%3abar%25 +found%3a%3ait +inbox +tag5 +unread +winner -- id:msg-001@notmuch-test-suite
+EOF
+
+notmuch dump --format=batch-tag | sort > OUTPUT
+notmuch restore --format=batch-tag < BACKUP
+test_expect_equal_file EXPECTED OUTPUT
+
+test_begin_subtest '--batch: unicode message-ids'
+
+${TEST_DIRECTORY}/random-corpus --config-path=${NOTMUCH_CONFIG} \
+ --num-messages=100
+
+notmuch dump --format=batch-tag | sed 's/^.* -- /+common_tag -- /' | \
+ sort > EXPECTED
+
+notmuch dump --format=batch-tag | sed 's/^.* -- / -- /' | \
+ notmuch restore --format=batch-tag
+
+notmuch tag --batch < EXPECTED
+
+notmuch dump --format=batch-tag| \
+ sort > OUTPUT
+
+test_expect_equal_file EXPECTED OUTPUT
+
+test_expect_code 1 "Empty tag names" 'notmuch tag + One'
+
+test_expect_code 1 "Tag name beginning with -" 'notmuch tag +- One'
+
+test_done
--- /dev/null
+#!/usr/bin/env bash
+test_description="--format=json output"
+. ./test-lib.sh
+
+test_begin_subtest "Show message: json"
+add_message "[subject]=\"json-show-subject\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[bcc]=\"test_suite+bcc@notmuchmail.org\"" "[reply-to]=\"test_suite+replyto@notmuchmail.org\"" "[body]=\"json-show-message\""
+output=$(notmuch show --format=json "json-show-message")
+test_expect_equal_json "$output" "[[[{\"id\": \"${gen_msg_id}\", \"match\": true, \"excluded\": false, \"filename\": \"${gen_msg_filename}\", \"timestamp\": 946728000, \"date_relative\": \"2000-01-01\", \"tags\": [\"inbox\",\"unread\"], \"headers\": {\"Subject\": \"json-show-subject\", \"From\": \"Notmuch Test Suite <test_suite@notmuchmail.org>\", \"To\": \"Notmuch Test Suite <test_suite@notmuchmail.org>\", \"Bcc\": \"test_suite+bcc@notmuchmail.org\", \"Reply-To\": \"test_suite+replyto@notmuchmail.org\", \"Date\": \"Sat, 01 Jan 2000 12:00:00 +0000\"}, \"body\": [{\"id\": 1, \"content-type\": \"text/plain\", \"content\": \"json-show-message\n\"}]}, []]]]"
+
+# This should be the same output as above.
+test_begin_subtest "Show message: json --body=true"
+output=$(notmuch show --format=json --body=true "json-show-message")
+test_expect_equal_json "$output" "[[[{\"id\": \"${gen_msg_id}\", \"match\": true, \"excluded\": false, \"filename\": \"${gen_msg_filename}\", \"timestamp\": 946728000, \"date_relative\": \"2000-01-01\", \"tags\": [\"inbox\",\"unread\"], \"headers\": {\"Subject\": \"json-show-subject\", \"From\": \"Notmuch Test Suite <test_suite@notmuchmail.org>\", \"To\": \"Notmuch Test Suite <test_suite@notmuchmail.org>\", \"Bcc\": \"test_suite+bcc@notmuchmail.org\", \"Reply-To\": \"test_suite+replyto@notmuchmail.org\", \"Date\": \"Sat, 01 Jan 2000 12:00:00 +0000\"}, \"body\": [{\"id\": 1, \"content-type\": \"text/plain\", \"content\": \"json-show-message\n\"}]}, []]]]"
+
+test_begin_subtest "Show message: json --body=false"
+output=$(notmuch show --format=json --body=false "json-show-message")
+test_expect_equal_json "$output" "[[[{\"id\": \"${gen_msg_id}\", \"match\": true, \"excluded\": false, \"filename\": \"${gen_msg_filename}\", \"timestamp\": 946728000, \"date_relative\": \"2000-01-01\", \"tags\": [\"inbox\",\"unread\"], \"headers\": {\"Subject\": \"json-show-subject\", \"From\": \"Notmuch Test Suite <test_suite@notmuchmail.org>\", \"To\": \"Notmuch Test Suite <test_suite@notmuchmail.org>\", \"Bcc\": \"test_suite+bcc@notmuchmail.org\", \"Reply-To\": \"test_suite+replyto@notmuchmail.org\", \"Date\": \"Sat, 01 Jan 2000 12:00:00 +0000\"}}, []]]]"
+
+test_begin_subtest "Search message: json"
+add_message "[subject]=\"json-search-subject\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[body]=\"json-search-message\""
+output=$(notmuch search --format=json "json-search-message" | notmuch_search_sanitize)
+test_expect_equal_json "$output" "[{\"thread\": \"XXX\",
+ \"timestamp\": 946728000,
+ \"date_relative\": \"2000-01-01\",
+ \"matched\": 1,
+ \"total\": 1,
+ \"authors\": \"Notmuch Test Suite\",
+ \"subject\": \"json-search-subject\",
+ \"query\": [\"id:$gen_msg_id\", null],
+ \"tags\": [\"inbox\",
+ \"unread\"]}]"
+
+test_begin_subtest "Show message: json, utf-8"
+add_message "[subject]=\"json-show-utf8-body-sübjéct\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[body]=\"jsön-show-méssage\""
+output=$(notmuch show --format=json "jsön-show-méssage")
+test_expect_equal_json "$output" "[[[{\"id\": \"${gen_msg_id}\", \"match\": true, \"excluded\": false, \"filename\": \"${gen_msg_filename}\", \"timestamp\": 946728000, \"date_relative\": \"2000-01-01\", \"tags\": [\"inbox\",\"unread\"], \"headers\": {\"Subject\": \"json-show-utf8-body-sübjéct\", \"From\": \"Notmuch Test Suite <test_suite@notmuchmail.org>\", \"To\": \"Notmuch Test Suite <test_suite@notmuchmail.org>\", \"Date\": \"Sat, 01 Jan 2000 12:00:00 +0000\"}, \"body\": [{\"id\": 1, \"content-type\": \"text/plain\", \"content\": \"jsön-show-méssage\n\"}]}, []]]]"
+
+test_begin_subtest "Show message: json, inline attachment filename"
+subject='json-show-inline-attachment-filename'
+id="json-show-inline-attachment-filename@notmuchmail.org"
+emacs_fcc_message \
+ "$subject" \
+ 'This is a test message with inline attachment with a filename' \
+ "(mml-attach-file \"$TEST_DIRECTORY/README\" nil nil \"inline\")
+ (message-goto-eoh)
+ (insert \"Message-ID: <$id>\n\")"
+output=$(notmuch show --format=json "id:$id")
+filename=$(notmuch search --output=files "id:$id")
+# Get length of README after base64-encoding, minus additional newline.
+attachment_length=$(( $(base64 $TEST_DIRECTORY/README | wc -c) - 1 ))
+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 <test_suite@notmuchmail.org>\", \"To\": \"test_suite@notmuchmail.org\", \"Date\": \"Sat, 01 Jan 2000 12:00:00 +0000\"}, \"body\": [{\"id\": 1, \"content-type\": \"multipart/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\", \"content-length\": $attachment_length, \"content-transfer-encoding\": \"base64\", \"filename\": \"README\"}]}]}, []]]]"
+
+test_begin_subtest "Search message: json, utf-8"
+add_message "[subject]=\"json-search-utf8-body-sübjéct\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[body]=\"jsön-search-méssage\""
+output=$(notmuch search --format=json "jsön-search-méssage" | notmuch_search_sanitize)
+test_expect_equal_json "$output" "[{\"thread\": \"XXX\",
+ \"timestamp\": 946728000,
+ \"date_relative\": \"2000-01-01\",
+ \"matched\": 1,
+ \"total\": 1,
+ \"authors\": \"Notmuch Test Suite\",
+ \"subject\": \"json-search-utf8-body-sübjéct\",
+ \"query\": [\"id:$gen_msg_id\", null],
+ \"tags\": [\"inbox\",
+ \"unread\"]}]"
+
+test_expect_code 20 "Format version: too low" \
+ "notmuch search --format-version=0 \\*"
+
+test_expect_code 21 "Format version: too high" \
+ "notmuch search --format-version=999 \\*"
+
+test_done
--- /dev/null
+#!/usr/bin/env bash
+test_description="--format=sexp output"
+. ./test-lib.sh
+
+test_begin_subtest "Show message: sexp"
+add_message "[subject]=\"sexp-show-subject\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[bcc]=\"test_suite+bcc@notmuchmail.org\"" "[reply-to]=\"test_suite+replyto@notmuchmail.org\"" "[body]=\"sexp-show-message\""
+output=$(notmuch show --format=sexp "sexp-show-message")
+test_expect_equal "$output" "((((:id \"${gen_msg_id}\" :match t :excluded nil :filename \"${gen_msg_filename}\" :timestamp 946728000 :date_relative \"2000-01-01\" :tags (\"inbox\" \"unread\") :headers (:Subject \"sexp-show-subject\" :From \"Notmuch Test Suite <test_suite@notmuchmail.org>\" :To \"Notmuch Test Suite <test_suite@notmuchmail.org>\" :Bcc \"test_suite+bcc@notmuchmail.org\" :Reply-To \"test_suite+replyto@notmuchmail.org\" :Date \"Sat, 01 Jan 2000 12:00:00 +0000\") :body ((:id 1 :content-type \"text/plain\" :content \"sexp-show-message\n\"))) ())))"
+
+# This should be the same output as above.
+test_begin_subtest "Show message: sexp --body=true"
+output=$(notmuch show --format=sexp --body=true "sexp-show-message")
+test_expect_equal "$output" "((((:id \"${gen_msg_id}\" :match t :excluded nil :filename \"${gen_msg_filename}\" :timestamp 946728000 :date_relative \"2000-01-01\" :tags (\"inbox\" \"unread\") :headers (:Subject \"sexp-show-subject\" :From \"Notmuch Test Suite <test_suite@notmuchmail.org>\" :To \"Notmuch Test Suite <test_suite@notmuchmail.org>\" :Bcc \"test_suite+bcc@notmuchmail.org\" :Reply-To \"test_suite+replyto@notmuchmail.org\" :Date \"Sat, 01 Jan 2000 12:00:00 +0000\") :body ((:id 1 :content-type \"text/plain\" :content \"sexp-show-message\n\"))) ())))"
+
+test_begin_subtest "Show message: sexp --body=false"
+output=$(notmuch show --format=sexp --body=false "sexp-show-message")
+test_expect_equal "$output" "((((:id \"${gen_msg_id}\" :match t :excluded nil :filename \"${gen_msg_filename}\" :timestamp 946728000 :date_relative \"2000-01-01\" :tags (\"inbox\" \"unread\") :headers (:Subject \"sexp-show-subject\" :From \"Notmuch Test Suite <test_suite@notmuchmail.org>\" :To \"Notmuch Test Suite <test_suite@notmuchmail.org>\" :Bcc \"test_suite+bcc@notmuchmail.org\" :Reply-To \"test_suite+replyto@notmuchmail.org\" :Date \"Sat, 01 Jan 2000 12:00:00 +0000\")) ())))"
+
+test_begin_subtest "Search message: sexp"
+add_message "[subject]=\"sexp-search-subject\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[body]=\"sexp-search-message\""
+output=$(notmuch search --format=sexp "sexp-search-message" | notmuch_search_sanitize)
+test_expect_equal "$output" "((:thread \"0000000000000002\" :timestamp 946728000 :date_relative \"2000-01-01\" :matched 1 :total 1 :authors \"Notmuch Test Suite\" :subject \"sexp-search-subject\" :query (\"id:$gen_msg_id\" nil) :tags (\"inbox\" \"unread\")))"
+
+test_begin_subtest "Show message: sexp, utf-8"
+add_message "[subject]=\"sexp-show-utf8-body-sübjéct\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[body]=\"jsön-show-méssage\""
+output=$(notmuch show --format=sexp "jsön-show-méssage")
+test_expect_equal "$output" "((((:id \"${gen_msg_id}\" :match t :excluded nil :filename \"${gen_msg_filename}\" :timestamp 946728000 :date_relative \"2000-01-01\" :tags (\"inbox\" \"unread\") :headers (:Subject \"sexp-show-utf8-body-sübjéct\" :From \"Notmuch Test Suite <test_suite@notmuchmail.org>\" :To \"Notmuch Test Suite <test_suite@notmuchmail.org>\" :Date \"Sat, 01 Jan 2000 12:00:00 +0000\") :body ((:id 1 :content-type \"text/plain\" :content \"jsön-show-méssage\n\"))) ())))"
+
+test_begin_subtest "Show message: sexp, inline attachment filename"
+subject='sexp-show-inline-attachment-filename'
+id="sexp-show-inline-attachment-filename@notmuchmail.org"
+emacs_fcc_message \
+ "$subject" \
+ 'This is a test message with inline attachment with a filename' \
+ "(mml-attach-file \"$TEST_DIRECTORY/README\" nil nil \"inline\")
+ (message-goto-eoh)
+ (insert \"Message-ID: <$id>\n\")"
+output=$(notmuch show --format=sexp "id:$id")
+filename=$(notmuch search --output=files "id:$id")
+# Get length of README after base64-encoding, minus additional newline.
+attachment_length=$(( $(base64 $TEST_DIRECTORY/README | wc -c) - 1 ))
+test_expect_equal "$output" "((((:id \"$id\" :match t :excluded nil :filename \"$filename\" :timestamp 946728000 :date_relative \"2000-01-01\" :tags (\"inbox\") :headers (:Subject \"sexp-show-inline-attachment-filename\" :From \"Notmuch Test Suite <test_suite@notmuchmail.org>\" :To \"test_suite@notmuchmail.org\" :Date \"Sat, 01 Jan 2000 12:00:00 +0000\") :body ((:id 1 :content-type \"multipart/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\" :content-transfer-encoding \"base64\" :content-length $attachment_length))))) ())))"
+
+test_begin_subtest "Search message: sexp, utf-8"
+add_message "[subject]=\"sexp-search-utf8-body-sübjéct\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[body]=\"jsön-search-méssage\""
+output=$(notmuch search --format=sexp "jsön-search-méssage" | notmuch_search_sanitize)
+test_expect_equal "$output" "((:thread \"0000000000000005\" :timestamp 946728000 :date_relative \"2000-01-01\" :matched 1 :total 1 :authors \"Notmuch Test Suite\" :subject \"sexp-search-utf8-body-sübjéct\" :query (\"id:$gen_msg_id\" nil) :tags (\"inbox\" \"unread\")))"
+
+
+test_done
--- /dev/null
+#!/usr/bin/env bash
+test_description="--format=text output"
+. ./test-lib.sh
+
+test_begin_subtest "Show message: text"
+add_message "[subject]=\"text-show-subject\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[body]=\"text-show-message\""
+output=$(notmuch show --format=text "text-show-message" | notmuch_show_sanitize_all)
+test_expect_equal "$output" "\
+\fmessage{ id:XXXXX depth:0 match:1 excluded:0 filename:XXXXX
+\fheader{
+Notmuch Test Suite <test_suite@notmuchmail.org> (2000-01-01) (inbox unread)
+Subject: text-show-subject
+From: Notmuch Test Suite <test_suite@notmuchmail.org>
+To: Notmuch Test Suite <test_suite@notmuchmail.org>
+Date: Sat, 01 Jan 2000 12:00:00 +0000
+\fheader}
+\fbody{
+\fpart{ ID: 1, Content-type: text/plain
+text-show-message
+\fpart}
+\fbody}
+\fmessage}"
+
+test_begin_subtest "Search message: text"
+add_message "[subject]=\"text-search-subject\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[body]=\"text-search-message\""
+output=$(notmuch search --format=text "text-search-message" | notmuch_search_sanitize)
+test_expect_equal "$output" \
+"thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; text-search-subject (inbox unread)"
+
+test_begin_subtest "Show message: text, utf-8"
+add_message "[subject]=\"text-show-utf8-body-sübjéct\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[body]=\"tëxt-show-méssage\""
+output=$(notmuch show --format=text "tëxt-show-méssage" | notmuch_show_sanitize_all)
+test_expect_equal "$output" "\
+\fmessage{ id:XXXXX depth:0 match:1 excluded:0 filename:XXXXX
+\fheader{
+Notmuch Test Suite <test_suite@notmuchmail.org> (2000-01-01) (inbox unread)
+Subject: text-show-utf8-body-sübjéct
+From: Notmuch Test Suite <test_suite@notmuchmail.org>
+To: Notmuch Test Suite <test_suite@notmuchmail.org>
+Date: Sat, 01 Jan 2000 12:00:00 +0000
+\fheader}
+\fbody{
+\fpart{ ID: 1, Content-type: text/plain
+tëxt-show-méssage
+\fpart}
+\fbody}
+\fmessage}"
+
+test_begin_subtest "Search message: text, utf-8"
+add_message "[subject]=\"text-search-utf8-body-sübjéct\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[body]=\"tëxt-search-méssage\""
+output=$(notmuch search --format=text "tëxt-search-méssage" | notmuch_search_sanitize)
+test_expect_equal "$output" \
+"thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; text-search-utf8-body-sübjéct (inbox unread)"
+
+add_email_corpus
+
+test_begin_subtest "Search message tags: text0"
+cat <<EOF > EXPECTED
+attachment inbox signed unread
+EOF
+notmuch search --format=text0 --output=tags '*' | xargs -0 | notmuch_search_sanitize > OUTPUT
+test_expect_equal_file EXPECTED OUTPUT
+
+# Use tr(1) to convert --output=text0 to --output=text for
+# comparison. Also translate newlines to spaces to fail with more
+# noise if they are present as delimiters instead of null
+# characters. This assumes there are no newlines in the data.
+test_begin_subtest "Compare text vs. text0 for threads"
+notmuch search --format=text --output=threads '*' | notmuch_search_sanitize > EXPECTED
+notmuch search --format=text0 --output=threads '*' | tr "\n\0" " \n" | notmuch_search_sanitize > OUTPUT
+test_expect_equal_file EXPECTED OUTPUT
+
+test_begin_subtest "Compare text vs. text0 for messages"
+notmuch search --format=text --output=messages '*' | notmuch_search_sanitize > EXPECTED
+notmuch search --format=text0 --output=messages '*' | tr "\n\0" " \n" | notmuch_search_sanitize > OUTPUT
+test_expect_equal_file EXPECTED OUTPUT
+
+test_begin_subtest "Compare text vs. text0 for files"
+notmuch search --format=text --output=files '*' | notmuch_search_sanitize > EXPECTED
+notmuch search --format=text0 --output=files '*' | tr "\n\0" " \n" | notmuch_search_sanitize > OUTPUT
+test_expect_equal_file EXPECTED OUTPUT
+
+test_begin_subtest "Compare text vs. text0 for tags"
+notmuch search --format=text --output=tags '*' | notmuch_search_sanitize > EXPECTED
+notmuch search --format=text0 --output=tags '*' | tr "\n\0" " \n" | notmuch_search_sanitize > OUTPUT
+test_expect_equal_file EXPECTED OUTPUT
+
+test_done
--- /dev/null
+#!/usr/bin/env bash
+test_description="output of multipart message"
+. ./test-lib.sh
+
+cat <<EOF > embedded_message
+From: Carl Worth <cworth@cworth.org>
+To: cworth@cworth.org
+Subject: html message
+Date: Fri, 05 Jan 2001 15:42:57 +0000
+User-Agent: Notmuch/0.5 (http://notmuchmail.org) Emacs/23.3.1 (i486-pc-linux-gnu)
+Message-ID: <87liy5ap01.fsf@yoom.home.cworth.org>
+MIME-Version: 1.0
+Content-Type: multipart/alternative; boundary="==-=-=="
+
+--==-=-==
+Content-Type: text/html
+
+<p>This is an embedded message, with a multipart/alternative part.</p>
+
+--==-=-==
+Content-Type: text/plain
+
+This is an embedded message, with a multipart/alternative part.
+
+--==-=-==--
+EOF
+
+cat <<EOF > ${MAIL_DIR}/multipart
+From: Carl Worth <cworth@cworth.org>
+To: cworth@cworth.org
+Subject: Multipart message
+Date: Fri, 05 Jan 2001 15:43:57 +0000
+User-Agent: Notmuch/0.5 (http://notmuchmail.org) Emacs/23.3.1 (i486-pc-linux-gnu)
+Message-ID: <87liy5ap00.fsf@yoom.home.cworth.org>
+MIME-Version: 1.0
+Content-Type: multipart/signed; boundary="==-=-=";
+ micalg=pgp-sha1; protocol="application/pgp-signature"
+
+--==-=-=
+Content-Type: multipart/mixed; boundary="=-=-="
+
+--=-=-=
+Content-Type: message/rfc822
+Content-Disposition: inline
+
+EOF
+cat embedded_message >> ${MAIL_DIR}/multipart
+cat <<EOF >> ${MAIL_DIR}/multipart
+
+--=-=-=
+Content-Disposition: attachment; filename=attachment
+
+This is a text attachment.
+
+--=-=-=
+
+And this message is signed.
+
+-Carl
+
+--=-=-=--
+
+--==-=-=
+Content-Type: application/pgp-signature
+
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v1.4.11 (GNU/Linux)
+
+iEYEARECAAYFAk3SA/gACgkQ6JDdNq8qSWj0sACghqVJEQJUs3yV8zbTzhgnSIcD
+W6cAmQE4dcYrx/LPLtYLZm1jsGauE5hE
+=zkga
+-----END PGP SIGNATURE-----
+--==-=-=--
+EOF
+
+cat <<EOF > ${MAIL_DIR}/base64-part-with-crlf
+From: Carl Worth <cworth@cworth.org>
+To: cworth@cworth.org
+Subject: Test message with a BASE64 encoded binary containing CRLF pair
+Date: Fri, 05 Jan 2001 15:43:57 +0000
+User-Agent: Notmuch/0.5 (http://notmuchmail.org) Emacs/23.3.1 (i486-pc-linux-gnu)
+Message-ID: <base64-part-with-crlf>
+MIME-Version: 1.0
+Content-Type: multipart/mixed; boundary="==-=-=";
+
+--==-=-=
+
+The attached BASE64-encoded part expands to a binary containing a CRLF
+pair (that is one bye of 0x0D followed by one byte of 0x0A). This is
+designed to ensure that notmuch is not corrupting the output of this
+part by converting the CRLF pair to an LF only (as would be appropriate
+for display of a text part on a Linux system, for example).
+
+The part should be a 3-byte file with the following sequence of 3
+hexadecimal bytes:
+
+ EF 0D 0A
+
+--==-=-=
+Content-Type: application/octet-stream
+Content-Disposition: attachment; filename=crlf.bin
+Content-Transfer-Encoding: base64
+
+7w0K
+--==-=-=--
+EOF
+notmuch new > /dev/null
+
+test_begin_subtest "--format=text --part=0, full message"
+notmuch show --format=text --part=0 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
+cat <<EOF >EXPECTED
+\fmessage{ id:87liy5ap00.fsf@yoom.home.cworth.org depth:0 match:1 excluded:0 filename:${MAIL_DIR}/multipart
+\fheader{
+Carl Worth <cworth@cworth.org> (2001-01-05) (attachment inbox signed unread)
+Subject: Multipart message
+From: Carl Worth <cworth@cworth.org>
+To: cworth@cworth.org
+Date: Fri, 05 Jan 2001 15:43:57 +0000
+\fheader}
+\fbody{
+\fpart{ ID: 1, Content-type: multipart/signed
+\fpart{ ID: 2, Content-type: multipart/mixed
+\fpart{ ID: 3, Content-type: message/rfc822
+\fheader{
+Subject: html message
+From: Carl Worth <cworth@cworth.org>
+To: cworth@cworth.org
+Date: Fri, 05 Jan 2001 15:42:57 +0000
+\fheader}
+\fbody{
+\fpart{ ID: 4, Content-type: multipart/alternative
+\fpart{ ID: 5, Content-type: text/html
+Non-text part: text/html
+\fpart}
+\fpart{ ID: 6, Content-type: text/plain
+This is an embedded message, with a multipart/alternative part.
+\fpart}
+\fpart}
+\fbody}
+\fpart}
+\fattachment{ ID: 7, Filename: attachment, Content-type: text/plain
+This is a text attachment.
+\fattachment}
+\fpart{ ID: 8, Content-type: text/plain
+And this message is signed.
+
+-Carl
+\fpart}
+\fpart}
+\fpart{ ID: 9, Content-type: application/pgp-signature
+Non-text part: application/pgp-signature
+\fpart}
+\fpart}
+\fbody}
+\fmessage}
+EOF
+test_expect_equal_file OUTPUT EXPECTED
+
+test_begin_subtest "--format=text --part=1, message body"
+notmuch show --format=text --part=1 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
+cat <<EOF >EXPECTED
+\fpart{ ID: 1, Content-type: multipart/signed
+\fpart{ ID: 2, Content-type: multipart/mixed
+\fpart{ ID: 3, Content-type: message/rfc822
+\fheader{
+Subject: html message
+From: Carl Worth <cworth@cworth.org>
+To: cworth@cworth.org
+Date: Fri, 05 Jan 2001 15:42:57 +0000
+\fheader}
+\fbody{
+\fpart{ ID: 4, Content-type: multipart/alternative
+\fpart{ ID: 5, Content-type: text/html
+Non-text part: text/html
+\fpart}
+\fpart{ ID: 6, Content-type: text/plain
+This is an embedded message, with a multipart/alternative part.
+\fpart}
+\fpart}
+\fbody}
+\fpart}
+\fattachment{ ID: 7, Filename: attachment, Content-type: text/plain
+This is a text attachment.
+\fattachment}
+\fpart{ ID: 8, Content-type: text/plain
+And this message is signed.
+
+-Carl
+\fpart}
+\fpart}
+\fpart{ ID: 9, Content-type: application/pgp-signature
+Non-text part: application/pgp-signature
+\fpart}
+\fpart}
+EOF
+test_expect_equal_file OUTPUT EXPECTED
+
+test_begin_subtest "--format=text --part=2, multipart/mixed"
+notmuch show --format=text --part=2 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
+cat <<EOF >EXPECTED
+\fpart{ ID: 2, Content-type: multipart/mixed
+\fpart{ ID: 3, Content-type: message/rfc822
+\fheader{
+Subject: html message
+From: Carl Worth <cworth@cworth.org>
+To: cworth@cworth.org
+Date: Fri, 05 Jan 2001 15:42:57 +0000
+\fheader}
+\fbody{
+\fpart{ ID: 4, Content-type: multipart/alternative
+\fpart{ ID: 5, Content-type: text/html
+Non-text part: text/html
+\fpart}
+\fpart{ ID: 6, Content-type: text/plain
+This is an embedded message, with a multipart/alternative part.
+\fpart}
+\fpart}
+\fbody}
+\fpart}
+\fattachment{ ID: 7, Filename: attachment, Content-type: text/plain
+This is a text attachment.
+\fattachment}
+\fpart{ ID: 8, Content-type: text/plain
+And this message is signed.
+
+-Carl
+\fpart}
+\fpart}
+EOF
+test_expect_equal_file OUTPUT EXPECTED
+
+test_begin_subtest "--format=text --part=3, rfc822 part"
+notmuch show --format=text --part=3 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
+cat <<EOF >EXPECTED
+\fpart{ ID: 3, Content-type: message/rfc822
+\fheader{
+Subject: html message
+From: Carl Worth <cworth@cworth.org>
+To: cworth@cworth.org
+Date: Fri, 05 Jan 2001 15:42:57 +0000
+\fheader}
+\fbody{
+\fpart{ ID: 4, Content-type: multipart/alternative
+\fpart{ ID: 5, Content-type: text/html
+Non-text part: text/html
+\fpart}
+\fpart{ ID: 6, Content-type: text/plain
+This is an embedded message, with a multipart/alternative part.
+\fpart}
+\fpart}
+\fbody}
+\fpart}
+EOF
+test_expect_equal_file OUTPUT EXPECTED
+
+test_begin_subtest "--format=text --part=4, rfc822's multipart"
+notmuch show --format=text --part=4 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
+cat <<EOF >EXPECTED
+\fpart{ ID: 4, Content-type: multipart/alternative
+\fpart{ ID: 5, Content-type: text/html
+Non-text part: text/html
+\fpart}
+\fpart{ ID: 6, Content-type: text/plain
+This is an embedded message, with a multipart/alternative part.
+\fpart}
+\fpart}
+EOF
+test_expect_equal_file OUTPUT EXPECTED
+
+test_begin_subtest "--format=text --part=5, rfc822's html part"
+notmuch show --format=text --part=5 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
+cat <<EOF >EXPECTED
+\fpart{ ID: 5, Content-type: text/html
+Non-text part: text/html
+\fpart}
+EOF
+test_expect_equal_file OUTPUT EXPECTED
+
+test_begin_subtest "--format=text --part=6, rfc822's text part"
+notmuch show --format=text --part=6 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
+cat <<EOF >EXPECTED
+\fpart{ ID: 6, Content-type: text/plain
+This is an embedded message, with a multipart/alternative part.
+\fpart}
+EOF
+test_expect_equal_file OUTPUT EXPECTED
+
+test_begin_subtest "--format=text --part=7, inline attachement"
+notmuch show --format=text --part=7 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
+cat <<EOF >EXPECTED
+\fattachment{ ID: 7, Filename: attachment, Content-type: text/plain
+This is a text attachment.
+\fattachment}
+EOF
+test_expect_equal_file OUTPUT EXPECTED
+
+test_begin_subtest "--format=text --part=8, plain text part"
+notmuch show --format=text --part=8 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
+cat <<EOF >EXPECTED
+\fpart{ ID: 8, Content-type: text/plain
+And this message is signed.
+
+-Carl
+\fpart}
+EOF
+test_expect_equal_file OUTPUT EXPECTED
+
+test_begin_subtest "--format=text --part=9, pgp signature (unverified)"
+notmuch show --format=text --part=9 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
+cat <<EOF >EXPECTED
+\fpart{ ID: 9, Content-type: application/pgp-signature
+Non-text part: application/pgp-signature
+\fpart}
+EOF
+test_expect_equal_file OUTPUT EXPECTED
+
+test_expect_success \
+ "--format=text --part=8, no part, expect error" \
+ "notmuch show --format=text --part=8 'id:87liy5ap00.fsf@yoom.home.cworth.org'"
+
+test_begin_subtest "--format=json --part=0, full message"
+notmuch show --format=json --part=0 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
+cat <<EOF >EXPECTED
+{"id": "87liy5ap00.fsf@yoom.home.cworth.org", "match": true, "excluded": false, "filename": "${MAIL_DIR}/multipart", "timestamp": 978709437, "date_relative": "2001-01-05", "tags": ["attachment","inbox","signed","unread"], "headers": {"Subject": "Multipart message", "From": "Carl Worth <cworth@cworth.org>", "To": "cworth@cworth.org", "Date": "Fri, 05 Jan 2001 15:43:57 +0000"}, "body": [
+{"id": 1, "content-type": "multipart/signed", "content": [
+{"id": 2, "content-type": "multipart/mixed", "content": [
+{"id": 3, "content-type": "message/rfc822", "content": [{"headers": {"Subject": "html message", "From": "Carl Worth <cworth@cworth.org>", "To": "cworth@cworth.org", "Date": "Fri, 05 Jan 2001 15:42:57 +0000"}, "body": [
+{"id": 4, "content-type": "multipart/alternative", "content": [
+{"id": 5, "content-type": "text/html", "content-length": 71},
+{"id": 6, "content-type": "text/plain", "content": "This is an embedded message, with a multipart/alternative part.\n"}]}]}]},
+{"id": 7, "content-type": "text/plain", "filename": "attachment", "content": "This is a text attachment.\n"},
+{"id": 8, "content-type": "text/plain", "content": "And this message is signed.\n\n-Carl\n"}]},
+{"id": 9, "content-type": "application/pgp-signature", "content-length": 197}]}]}
+EOF
+test_expect_equal_json "$(cat OUTPUT)" "$(cat EXPECTED)"
+
+test_begin_subtest "--format=json --part=1, message body"
+notmuch show --format=json --part=1 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
+cat <<EOF >EXPECTED
+{"id": 1, "content-type": "multipart/signed", "content": [
+{"id": 2, "content-type": "multipart/mixed", "content": [
+{"id": 3, "content-type": "message/rfc822", "content": [{"headers": {"Subject": "html message", "From": "Carl Worth <cworth@cworth.org>", "To": "cworth@cworth.org", "Date": "Fri, 05 Jan 2001 15:42:57 +0000"}, "body": [
+{"id": 4, "content-type": "multipart/alternative", "content": [
+{"id": 5, "content-type": "text/html", "content-length": 71},
+{"id": 6, "content-type": "text/plain", "content": "This is an embedded message, with a multipart/alternative part.\n"}]}]}]},
+{"id": 7, "content-type": "text/plain", "filename": "attachment", "content": "This is a text attachment.\n"},
+{"id": 8, "content-type": "text/plain", "content": "And this message is signed.\n\n-Carl\n"}]},
+{"id": 9, "content-type": "application/pgp-signature", "content-length": 197}]}
+EOF
+test_expect_equal_json "$(cat OUTPUT)" "$(cat EXPECTED)"
+
+test_begin_subtest "--format=json --part=2, multipart/mixed"
+notmuch show --format=json --part=2 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
+cat <<EOF >EXPECTED
+{"id": 2, "content-type": "multipart/mixed", "content": [
+{"id": 3, "content-type": "message/rfc822", "content": [{"headers": {"Subject": "html message", "From": "Carl Worth <cworth@cworth.org>", "To": "cworth@cworth.org", "Date": "Fri, 05 Jan 2001 15:42:57 +0000"}, "body": [
+{"id": 4, "content-type": "multipart/alternative", "content": [
+{"id": 5, "content-type": "text/html", "content-length": 71},
+{"id": 6, "content-type": "text/plain", "content": "This is an embedded message, with a multipart/alternative part.\n"}]}]}]},
+{"id": 7, "content-type": "text/plain", "filename": "attachment", "content": "This is a text attachment.\n"},
+{"id": 8, "content-type": "text/plain", "content": "And this message is signed.\n\n-Carl\n"}]}
+EOF
+test_expect_equal_json "$(cat OUTPUT)" "$(cat EXPECTED)"
+
+test_begin_subtest "--format=json --part=3, rfc822 part"
+notmuch show --format=json --part=3 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
+cat <<EOF >EXPECTED
+{"id": 3, "content-type": "message/rfc822", "content": [{"headers": {"Subject": "html message", "From": "Carl Worth <cworth@cworth.org>", "To": "cworth@cworth.org", "Date": "Fri, 05 Jan 2001 15:42:57 +0000"}, "body": [
+{"id": 4, "content-type": "multipart/alternative", "content": [
+{"id": 5, "content-type": "text/html", "content-length": 71},
+{"id": 6, "content-type": "text/plain", "content": "This is an embedded message, with a multipart/alternative part.\n"}]}]}]}
+EOF
+test_expect_equal_json "$(cat OUTPUT)" "$(cat EXPECTED)"
+
+test_begin_subtest "--format=json --part=4, rfc822's multipart/alternative"
+notmuch show --format=json --part=4 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
+cat <<EOF >EXPECTED
+{"id": 4, "content-type": "multipart/alternative", "content": [
+{"id": 5, "content-type": "text/html", "content-length": 71},
+{"id": 6, "content-type": "text/plain", "content": "This is an embedded message, with a multipart/alternative part.\n"}]}
+EOF
+test_expect_equal_json "$(cat OUTPUT)" "$(cat EXPECTED)"
+
+test_begin_subtest "--format=json --part=5, rfc822's html part"
+notmuch show --format=json --part=5 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
+cat <<EOF >EXPECTED
+{"id": 5, "content-type": "text/html", "content-length": 71}
+EOF
+test_expect_equal_json "$(cat OUTPUT)" "$(cat EXPECTED)"
+
+test_begin_subtest "--format=json --part=6, rfc822's text part"
+notmuch show --format=json --part=6 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
+cat <<EOF >EXPECTED
+{"id": 6, "content-type": "text/plain", "content": "This is an embedded message, with a multipart/alternative part.\n"}
+EOF
+test_expect_equal_json "$(cat OUTPUT)" "$(cat EXPECTED)"
+
+test_begin_subtest "--format=json --part=7, inline attachment"
+notmuch show --format=json --part=7 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
+cat <<EOF >EXPECTED
+{"id": 7, "content-type": "text/plain", "filename": "attachment", "content": "This is a text attachment.\n"}
+EOF
+test_expect_equal_json "$(cat OUTPUT)" "$(cat EXPECTED)"
+
+test_begin_subtest "--format=json --part=8, plain text part"
+notmuch show --format=json --part=8 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
+cat <<EOF >EXPECTED
+{"id": 8, "content-type": "text/plain", "content": "And this message is signed.\n\n-Carl\n"}
+EOF
+test_expect_equal_json "$(cat OUTPUT)" "$(cat EXPECTED)"
+
+test_begin_subtest "--format=json --part=9, pgp signature (unverified)"
+notmuch show --format=json --part=9 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
+cat <<EOF >EXPECTED
+{"id": 9, "content-type": "application/pgp-signature", "content-length": 197}
+EOF
+test_expect_equal_json "$(cat OUTPUT)" "$(cat EXPECTED)"
+
+test_expect_success \
+ "--format=json --part=10, no part, expect error" \
+ "notmuch show --format=json --part=10 'id:87liy5ap00.fsf@yoom.home.cworth.org'"
+
+test_begin_subtest "--format=raw"
+notmuch show --format=raw 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
+test_expect_equal_file OUTPUT "${MAIL_DIR}"/multipart
+
+test_begin_subtest "--format=raw --part=0, full message"
+notmuch show --format=raw --part=0 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
+test_expect_equal_file OUTPUT "${MAIL_DIR}"/multipart
+
+test_begin_subtest "--format=raw --part=1, message body"
+notmuch show --format=raw --part=1 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
+test_expect_equal_file OUTPUT "${MAIL_DIR}"/multipart
+
+test_begin_subtest "--format=raw --part=2, multipart/mixed"
+notmuch show --format=raw --part=2 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
+cat <<EOF >EXPECTED
+Content-Type: multipart/mixed; boundary="=-=-="
+
+--=-=-=
+Content-Type: message/rfc822
+Content-Disposition: inline
+
+From: Carl Worth <cworth@cworth.org>
+To: cworth@cworth.org
+Subject: html message
+Date: Fri, 05 Jan 2001 15:42:57 +0000
+User-Agent: Notmuch/0.5 (http://notmuchmail.org) Emacs/23.3.1 (i486-pc-linux-gnu)
+Message-ID: <87liy5ap01.fsf@yoom.home.cworth.org>
+MIME-Version: 1.0
+Content-Type: multipart/alternative; boundary="==-=-=="
+
+--==-=-==
+Content-Type: text/html
+
+<p>This is an embedded message, with a multipart/alternative part.</p>
+
+--==-=-==
+Content-Type: text/plain
+
+This is an embedded message, with a multipart/alternative part.
+
+--==-=-==--
+
+--=-=-=
+Content-Disposition: attachment; filename=attachment
+
+This is a text attachment.
+
+--=-=-=
+
+And this message is signed.
+
+-Carl
+
+--=-=-=--
+EOF
+test_expect_equal_file OUTPUT EXPECTED
+
+test_begin_subtest "--format=raw --part=3, rfc822 part"
+notmuch show --format=raw --part=3 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
+test_expect_equal_file OUTPUT embedded_message
+
+test_begin_subtest "--format=raw --part=4, rfc822's multipart"
+notmuch show --format=raw --part=4 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
+cat <<EOF >EXPECTED
+From: Carl Worth <cworth@cworth.org>
+To: cworth@cworth.org
+Subject: html message
+Date: Fri, 05 Jan 2001 15:42:57 +0000
+User-Agent: Notmuch/0.5 (http://notmuchmail.org) Emacs/23.3.1 (i486-pc-linux-gnu)
+Message-ID: <87liy5ap01.fsf@yoom.home.cworth.org>
+MIME-Version: 1.0
+Content-Type: multipart/alternative; boundary="==-=-=="
+
+--==-=-==
+Content-Type: text/html
+
+<p>This is an embedded message, with a multipart/alternative part.</p>
+
+--==-=-==
+Content-Type: text/plain
+
+This is an embedded message, with a multipart/alternative part.
+
+--==-=-==--
+EOF
+test_expect_equal_file OUTPUT EXPECTED
+
+test_begin_subtest "--format=raw --part=5, rfc822's html part"
+notmuch show --format=raw --part=5 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
+cat <<EOF >EXPECTED
+<p>This is an embedded message, with a multipart/alternative part.</p>
+EOF
+test_expect_equal_file OUTPUT EXPECTED
+
+test_begin_subtest "--format=raw --part=6, rfc822's text part"
+notmuch show --format=raw --part=6 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
+cat <<EOF >EXPECTED
+This is an embedded message, with a multipart/alternative part.
+EOF
+test_expect_equal_file OUTPUT EXPECTED
+
+test_begin_subtest "--format=raw --part=7, inline attachment"
+notmuch show --format=raw --part=7 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
+cat <<EOF >EXPECTED
+This is a text attachment.
+EOF
+test_expect_equal_file OUTPUT EXPECTED
+
+test_begin_subtest "--format=raw --part=8, plain text part"
+notmuch show --format=raw --part=8 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
+cat <<EOF >EXPECTED
+And this message is signed.
+
+-Carl
+EOF
+test_expect_equal_file OUTPUT EXPECTED
+
+test_begin_subtest "--format=raw --part=9, pgp signature (unverified)"
+notmuch show --format=raw --part=9 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
+# output should *not* include newline
+echo >>OUTPUT
+cat <<EOF >EXPECTED
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v1.4.11 (GNU/Linux)
+
+iEYEARECAAYFAk3SA/gACgkQ6JDdNq8qSWj0sACghqVJEQJUs3yV8zbTzhgnSIcD
+W6cAmQE4dcYrx/LPLtYLZm1jsGauE5hE
+=zkga
+-----END PGP SIGNATURE-----
+EOF
+test_expect_equal_file OUTPUT EXPECTED
+
+test_expect_success \
+ "--format=raw --part=10, no part, expect error" \
+ "notmuch show --format=raw --part=8 'id:87liy5ap00.fsf@yoom.home.cworth.org'"
+
+test_begin_subtest "--format=mbox"
+notmuch show --format=mbox 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
+printf "From cworth@cworth.org Fri Jan 5 15:43:57 2001\n" >EXPECTED
+cat "${MAIL_DIR}"/multipart >>EXPECTED
+# mbox output is expected to include a blank line
+echo >>EXPECTED
+test_expect_equal_file OUTPUT EXPECTED
+
+test_expect_success \
+ "--format=mbox --part=1, incompatible, expect error" \
+ "! notmuch show --format=mbox --part=1 'id:87liy5ap00.fsf@yoom.home.cworth.org'"
+
+test_begin_subtest "'notmuch reply' to a multipart message"
+notmuch reply 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
+cat <<EOF >EXPECTED
+From: Notmuch Test Suite <test_suite@notmuchmail.org>
+Subject: Re: Multipart message
+To: Carl Worth <cworth@cworth.org>, cworth@cworth.org
+In-Reply-To: <87liy5ap00.fsf@yoom.home.cworth.org>
+References: <87liy5ap00.fsf@yoom.home.cworth.org>
+
+On Fri, 05 Jan 2001 15:43:57 +0000, Carl Worth <cworth@cworth.org> wrote:
+> From: Carl Worth <cworth@cworth.org>
+> To: cworth@cworth.org
+> Subject: html message
+> Date: Fri, 05 Jan 2001 15:42:57 +0000
+>
+Non-text part: text/html
+> This is an embedded message, with a multipart/alternative part.
+> This is a text attachment.
+> And this message is signed.
+>
+> -Carl
+EOF
+test_expect_equal_file OUTPUT EXPECTED
+
+test_begin_subtest "'notmuch reply' to a multipart message with json format"
+notmuch reply --format=json 'id:87liy5ap00.fsf@yoom.home.cworth.org' | notmuch_json_show_sanitize >OUTPUT
+notmuch_json_show_sanitize <<EOF >EXPECTED
+{"reply-headers": {"Subject": "Re: Multipart message",
+ "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
+ "To": "Carl Worth <cworth@cworth.org>, cworth@cworth.org",
+ "In-reply-to": "<87liy5ap00.fsf@yoom.home.cworth.org>",
+ "References": "<87liy5ap00.fsf@yoom.home.cworth.org>"},
+ "original": {"id": "XXXXX",
+ "match": false,
+ "excluded": false,
+ "filename": "YYYYY",
+ "timestamp": 978709437,
+ "date_relative": "2001-01-05",
+ "tags": ["attachment","inbox","signed","unread"],
+ "headers": {"Subject": "Multipart message",
+ "From": "Carl Worth <cworth@cworth.org>",
+ "To": "cworth@cworth.org",
+ "Date": "Fri, 05 Jan 2001 15:43:57 +0000"},
+ "body": [{"id": 1,
+ "content-type": "multipart/signed",
+ "content": [{"id": 2,
+ "content-type": "multipart/mixed",
+ "content": [{"id": 3,
+ "content-type": "message/rfc822",
+ "content": [{"headers": {"Subject": "html message",
+ "From": "Carl Worth <cworth@cworth.org>",
+ "To": "cworth@cworth.org",
+ "Date": "Fri, 05 Jan 2001 15:42:57 +0000"},
+ "body": [{"id": 4,
+ "content-type": "multipart/alternative",
+ "content": [{"id": 5,
+ "content-type": "text/html",
+ "content-length": 71},
+ {"id": 6,
+ "content-type": "text/plain",
+ "content": "This is an embedded message, with a multipart/alternative part.\n"}]}]}]},
+ {"id": 7,
+ "content-type": "text/plain",
+ "filename": "attachment",
+ "content": "This is a text attachment.\n"},
+ {"id": 8,
+ "content-type": "text/plain",
+ "content": "And this message is signed.\n\n-Carl\n"}]},
+ {"id": 9,
+ "content-type": "application/pgp-signature",
+ "content-length": 197}]}]}}
+EOF
+test_expect_equal_json "$(cat OUTPUT)" "$(cat EXPECTED)"
+
+test_begin_subtest "'notmuch show --part' does not corrupt a part with CRLF pair"
+notmuch show --format=raw --part=3 id:base64-part-with-crlf > crlf.out
+echo -n -e "\xEF\x0D\x0A" > crlf.expected
+test_expect_equal_file crlf.out crlf.expected
+
+
+# The ISO-8859-1 encoding of U+00BD is a single byte: octal 275
+# (Portability note: Dollar-Single ($'...', ANSI C-style escape sequences)
+# quoting works on bash, ksh, zsh, *BSD sh but not on dash, ash nor busybox sh)
+readonly u_00bd_latin1=$'\275'
+
+# The Unicode fraction symbol 1/2 is U+00BD and is encoded
+# in UTF-8 as two bytes: octal 302 275
+readonly u_00bd_utf8=$'\302\275'
+
+cat <<EOF > ${MAIL_DIR}/include-html
+From: A <a@example.com>
+To: B <b@example.com>
+Subject: html message
+Date: Sat, 01 January 2000 00:00:00 +0000
+Message-ID: <htmlmessage>
+MIME-Version: 1.0
+Content-Type: multipart/alternative; boundary="==-=="
+
+--==-==
+Content-Type: text/html; charset=UTF-8
+
+<p>0.5 equals ${u_00bd_utf8}</p>
+
+--==-==
+Content-Type: text/html; charset=ISO-8859-1
+
+<p>0.5 equals ${u_00bd_latin1}</p>
+
+--==-==
+Content-Type: text/plain; charset=UTF-8
+
+0.5 equals ${u_00bd_utf8}
+
+--==-==--
+EOF
+
+notmuch new > /dev/null
+
+cat_expected_head ()
+{
+ cat <<EOF
+[[[{"id": "htmlmessage", "match":true, "excluded": false, "date_relative":"2000-01-01",
+ "timestamp": 946684800,
+ "filename": "${MAIL_DIR}/include-html",
+ "tags": ["inbox", "unread"],
+ "headers": { "Date": "Sat, 01 Jan 2000 00:00:00 +0000", "From": "A <a@example.com>",
+ "Subject": "html message", "To": "B <b@example.com>"},
+ "body": [{
+ "content-type": "multipart/alternative", "id": 1,
+EOF
+}
+
+cat_expected_head > EXPECTED.nohtml
+cat <<EOF >> EXPECTED.nohtml
+"content": [
+ { "id": 2, "content-charset": "UTF-8", "content-length": 21, "content-type": "text/html"},
+ { "id": 3, "content-charset": "ISO-8859-1", "content-length": 20, "content-type": "text/html"},
+ { "id": 4, "content-type": "text/plain", "content": "0.5 equals \\u00bd\\n"}
+]}]},[]]]]
+EOF
+
+# Both the UTF-8 and ISO-8859-1 part should have U+00BD
+cat_expected_head > EXPECTED.withhtml
+cat <<EOF >> EXPECTED.withhtml
+"content": [
+ { "id": 2, "content-type": "text/html", "content": "<p>0.5 equals \\u00bd</p>\\n"},
+ { "id": 3, "content-type": "text/html", "content": "<p>0.5 equals \\u00bd</p>\\n"},
+ { "id": 4, "content-type": "text/plain", "content": "0.5 equals \\u00bd\\n"}
+]}]},[]]]]
+EOF
+
+test_begin_subtest "html parts excluded by default"
+notmuch show --format=json id:htmlmessage > OUTPUT
+test_expect_equal_json "$(cat OUTPUT)" "$(cat EXPECTED.nohtml)"
+
+test_begin_subtest "html parts included"
+notmuch show --format=json --include-html id:htmlmessage > OUTPUT
+test_expect_equal_json "$(cat OUTPUT)" "$(cat EXPECTED.withhtml)"
+
+test_done
--- /dev/null
+#!/usr/bin/env bash
+test_description="naming of threads with changing subject"
+. ./test-lib.sh
+
+test_begin_subtest "Initial thread name (oldest-first search)"
+add_message '[subject]="thread-naming: Initial thread subject"' \
+ '[date]="Fri, 05 Jan 2001 15:43:56 -0000"'
+first=${gen_msg_cnt}
+parent=${gen_msg_id}
+add_message '[subject]="thread-naming: Older changed subject"' \
+ '[date]="Sat, 06 Jan 2001 15:43:56 -0000"' \
+ "[in-reply-to]=\<$parent\>"
+add_message '[subject]="thread-naming: Newer changed subject"' \
+ '[date]="Sun, 07 Jan 2001 15:43:56 -0000"' \
+ "[in-reply-to]=\<$parent\>"
+add_message '[subject]="thread-naming: Final thread subject"' \
+ '[date]="Mon, 08 Jan 2001 15:43:56 -0000"' \
+ "[in-reply-to]=\<$parent\>"
+final=${gen_msg_id}
+output=$(notmuch search --sort=oldest-first thread-naming and tag:inbox | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2001-01-05 [4/4] Notmuch Test Suite; thread-naming: Initial thread subject (inbox unread)"
+
+test_begin_subtest "Initial thread name (newest-first search)"
+output=$(notmuch search --sort=newest-first thread-naming and tag:inbox | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2001-01-08 [4/4] Notmuch Test Suite; thread-naming: Final thread subject (inbox unread)"
+
+# Remove oldest and newest messages from search results
+notmuch tag -inbox id:$parent or id:$final
+
+test_begin_subtest "Changed thread name (oldest-first search)"
+output=$(notmuch search --sort=oldest-first thread-naming and tag:inbox | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2001-01-06 [2/4] Notmuch Test Suite; thread-naming: Older changed subject (inbox unread)"
+
+test_begin_subtest "Changed thread name (newest-first search)"
+output=$(notmuch search --sort=newest-first thread-naming and tag:inbox | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2001-01-07 [2/4] Notmuch Test Suite; thread-naming: Newer changed subject (inbox unread)"
+
+test_begin_subtest "Ignore added reply prefix (Re:)"
+add_message '[subject]="Re: thread-naming: Initial thread subject"' \
+ '[date]="Tue, 09 Jan 2001 15:43:45 -0000"' \
+ "[in-reply-to]=\<$parent\>"
+output=$(notmuch search --sort=newest-first thread-naming and tag:inbox | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2001-01-09 [3/5] Notmuch Test Suite; thread-naming: Initial thread subject (inbox unread)"
+
+test_begin_subtest "Ignore added reply prefix (Aw:)"
+add_message '[subject]="Aw: thread-naming: Initial thread subject"' \
+ '[date]="Wed, 10 Jan 2001 15:43:45 -0000"' \
+ "[in-reply-to]=\<$parent\>"
+output=$(notmuch search --sort=newest-first thread-naming and tag:inbox | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2001-01-10 [4/6] Notmuch Test Suite; thread-naming: Initial thread subject (inbox unread)"
+
+test_begin_subtest "Ignore added reply prefix (Vs:)"
+add_message '[subject]="Vs: thread-naming: Initial thread subject"' \
+ '[date]="Thu, 11 Jan 2001 15:43:45 -0000"' \
+ "[in-reply-to]=\<$parent\>"
+output=$(notmuch search --sort=newest-first thread-naming and tag:inbox | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2001-01-11 [5/7] Notmuch Test Suite; thread-naming: Initial thread subject (inbox unread)"
+
+test_begin_subtest "Ignore added reply prefix (Sv:)"
+add_message '[subject]="Sv: thread-naming: Initial thread subject"' \
+ '[date]="Fri, 12 Jan 2001 15:43:45 -0000"' \
+ "[in-reply-to]=\<$parent\>"
+output=$(notmuch search --sort=newest-first thread-naming and tag:inbox | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2001-01-12 [6/8] Notmuch Test Suite; thread-naming: Initial thread subject (inbox unread)"
+
+test_begin_subtest 'Test order of messages in "notmuch show"'
+output=$(notmuch show thread-naming | notmuch_show_sanitize)
+test_expect_equal "$output" "\fmessage{ id:msg-$(printf "%03d" $first)@notmuch-test-suite depth:0 match:1 excluded:0 filename:/XXX/mail/msg-$(printf "%03d" $first)
+\fheader{
+Notmuch Test Suite <test_suite@notmuchmail.org> (2001-01-05) (unread)
+Subject: thread-naming: Initial thread subject
+From: Notmuch Test Suite <test_suite@notmuchmail.org>
+To: Notmuch Test Suite <test_suite@notmuchmail.org>
+Date: Fri, 05 Jan 2001 15:43:56 +0000
+\fheader}
+\fbody{
+\fpart{ ID: 1, Content-type: text/plain
+This is just a test message (#$first)
+\fpart}
+\fbody}
+\fmessage}
+\fmessage{ id:msg-$(printf "%03d" $((first + 1)))@notmuch-test-suite depth:1 match:1 excluded:0 filename:/XXX/mail/msg-$(printf "%03d" $((first + 1)))
+\fheader{
+Notmuch Test Suite <test_suite@notmuchmail.org> (2001-01-06) (inbox unread)
+Subject: thread-naming: Older changed subject
+From: Notmuch Test Suite <test_suite@notmuchmail.org>
+To: Notmuch Test Suite <test_suite@notmuchmail.org>
+Date: Sat, 06 Jan 2001 15:43:56 +0000
+\fheader}
+\fbody{
+\fpart{ ID: 1, Content-type: text/plain
+This is just a test message (#$((first + 1)))
+\fpart}
+\fbody}
+\fmessage}
+\fmessage{ id:msg-$(printf "%03d" $((first + 2)))@notmuch-test-suite depth:1 match:1 excluded:0 filename:/XXX/mail/msg-$(printf "%03d" $((first + 2)))
+\fheader{
+Notmuch Test Suite <test_suite@notmuchmail.org> (2001-01-07) (inbox unread)
+Subject: thread-naming: Newer changed subject
+From: Notmuch Test Suite <test_suite@notmuchmail.org>
+To: Notmuch Test Suite <test_suite@notmuchmail.org>
+Date: Sun, 07 Jan 2001 15:43:56 +0000
+\fheader}
+\fbody{
+\fpart{ ID: 1, Content-type: text/plain
+This is just a test message (#$((first + 2)))
+\fpart}
+\fbody}
+\fmessage}
+\fmessage{ id:msg-$(printf "%03d" $((first + 3)))@notmuch-test-suite depth:1 match:1 excluded:0 filename:/XXX/mail/msg-$(printf "%03d" $((first + 3)))
+\fheader{
+Notmuch Test Suite <test_suite@notmuchmail.org> (2001-01-08) (unread)
+Subject: thread-naming: Final thread subject
+From: Notmuch Test Suite <test_suite@notmuchmail.org>
+To: Notmuch Test Suite <test_suite@notmuchmail.org>
+Date: Mon, 08 Jan 2001 15:43:56 +0000
+\fheader}
+\fbody{
+\fpart{ ID: 1, Content-type: text/plain
+This is just a test message (#$((first + 3)))
+\fpart}
+\fbody}
+\fmessage}
+\fmessage{ id:msg-$(printf "%03d" $((first + 4)))@notmuch-test-suite depth:1 match:1 excluded:0 filename:/XXX/mail/msg-$(printf "%03d" $((first + 4)))
+\fheader{
+Notmuch Test Suite <test_suite@notmuchmail.org> (2001-01-09) (inbox unread)
+Subject: Re: thread-naming: Initial thread subject
+From: Notmuch Test Suite <test_suite@notmuchmail.org>
+To: Notmuch Test Suite <test_suite@notmuchmail.org>
+Date: Tue, 09 Jan 2001 15:43:45 +0000
+\fheader}
+\fbody{
+\fpart{ ID: 1, Content-type: text/plain
+This is just a test message (#$((first + 4)))
+\fpart}
+\fbody}
+\fmessage}
+\fmessage{ id:msg-$(printf "%03d" $((first + 5)))@notmuch-test-suite depth:1 match:1 excluded:0 filename:/XXX/mail/msg-$(printf "%03d" $((first + 5)))
+\fheader{
+Notmuch Test Suite <test_suite@notmuchmail.org> (2001-01-10) (inbox unread)
+Subject: Aw: thread-naming: Initial thread subject
+From: Notmuch Test Suite <test_suite@notmuchmail.org>
+To: Notmuch Test Suite <test_suite@notmuchmail.org>
+Date: Wed, 10 Jan 2001 15:43:45 +0000
+\fheader}
+\fbody{
+\fpart{ ID: 1, Content-type: text/plain
+This is just a test message (#$((first + 5)))
+\fpart}
+\fbody}
+\fmessage}
+\fmessage{ id:msg-$(printf "%03d" $((first + 6)))@notmuch-test-suite depth:1 match:1 excluded:0 filename:/XXX/mail/msg-$(printf "%03d" $((first + 6)))
+\fheader{
+Notmuch Test Suite <test_suite@notmuchmail.org> (2001-01-11) (inbox unread)
+Subject: Vs: thread-naming: Initial thread subject
+From: Notmuch Test Suite <test_suite@notmuchmail.org>
+To: Notmuch Test Suite <test_suite@notmuchmail.org>
+Date: Thu, 11 Jan 2001 15:43:45 +0000
+\fheader}
+\fbody{
+\fpart{ ID: 1, Content-type: text/plain
+This is just a test message (#$((first + 6)))
+\fpart}
+\fbody}
+\fmessage}
+\fmessage{ id:msg-$(printf "%03d" $((first + 7)))@notmuch-test-suite depth:1 match:1 excluded:0 filename:/XXX/mail/msg-$(printf "%03d" $((first + 7)))
+\fheader{
+Notmuch Test Suite <test_suite@notmuchmail.org> (2001-01-12) (inbox unread)
+Subject: Sv: thread-naming: Initial thread subject
+From: Notmuch Test Suite <test_suite@notmuchmail.org>
+To: Notmuch Test Suite <test_suite@notmuchmail.org>
+Date: Fri, 12 Jan 2001 15:43:45 +0000
+\fheader}
+\fbody{
+\fpart{ ID: 1, Content-type: text/plain
+This is just a test message (#$((first + 7)))
+\fpart}
+\fbody}
+\fmessage}"
+test_done
--- /dev/null
+#!/usr/bin/env bash
+
+test_description='notmuch show --format=raw'
+. ./test-lib.sh
+
+add_message
+add_message
+
+test_begin_subtest "Attempt to show multiple raw messages"
+output=$(notmuch show --format=raw "*" 2>&1)
+test_expect_equal "$output" "Error: search term did not match precisely one message."
+
+test_begin_subtest "Show a raw message"
+output=$(notmuch show --format=raw id:msg-001@notmuch-test-suite | notmuch_date_sanitize)
+test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@notmuchmail.org>
+To: Notmuch Test Suite <test_suite@notmuchmail.org>
+Message-Id: <msg-001@notmuch-test-suite>
+Subject: Test message #1
+Date: GENERATED_DATE
+
+This is just a test message (#1)"
+
+test_begin_subtest "Show another raw message"
+output=$(notmuch show --format=raw id:msg-002@notmuch-test-suite | notmuch_date_sanitize)
+test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@notmuchmail.org>
+To: Notmuch Test Suite <test_suite@notmuchmail.org>
+Message-Id: <msg-002@notmuch-test-suite>
+Subject: Test message #2
+Date: GENERATED_DATE
+
+This is just a test message (#2)"
+
+test_done
--- /dev/null
+#!/usr/bin/env bash
+test_description="\"notmuch reply\" in several variations"
+. ./test-lib.sh
+
+test_begin_subtest "Basic reply"
+add_message '[from]="Sender <sender@example.com>"' \
+ [to]=test_suite@notmuchmail.org \
+ [subject]=notmuch-reply-test \
+ '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
+ '[body]="basic reply test"'
+
+output=$(notmuch reply id:${gen_msg_id})
+test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@notmuchmail.org>
+Subject: Re: notmuch-reply-test
+To: Sender <sender@example.com>
+In-Reply-To: <${gen_msg_id}>
+References: <${gen_msg_id}>
+
+On Tue, 05 Jan 2010 15:43:56 -0000, Sender <sender@example.com> wrote:
+> basic reply test"
+
+test_begin_subtest "Multiple recipients"
+add_message '[from]="Sender <sender@example.com>"' \
+ '[to]="test_suite@notmuchmail.org, Someone Else <someone@example.com>"' \
+ [subject]=notmuch-reply-test \
+ '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
+ '[body]="Multiple recipients"'
+
+output=$(notmuch reply id:${gen_msg_id})
+test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@notmuchmail.org>
+Subject: Re: notmuch-reply-test
+To: Sender <sender@example.com>, Someone Else <someone@example.com>
+In-Reply-To: <${gen_msg_id}>
+References: <${gen_msg_id}>
+
+On Tue, 05 Jan 2010 15:43:56 -0000, Sender <sender@example.com> wrote:
+> Multiple recipients"
+
+test_begin_subtest "Reply with CC"
+add_message '[from]="Sender <sender@example.com>"' \
+ [to]=test_suite@notmuchmail.org \
+ '[cc]="Other Parties <cc@example.com>"' \
+ [subject]=notmuch-reply-test \
+ '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
+ '[body]="reply with CC"'
+
+output=$(notmuch reply id:${gen_msg_id})
+test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@notmuchmail.org>
+Subject: Re: notmuch-reply-test
+To: Sender <sender@example.com>
+Cc: Other Parties <cc@example.com>
+In-Reply-To: <${gen_msg_id}>
+References: <${gen_msg_id}>
+
+On Tue, 05 Jan 2010 15:43:56 -0000, Sender <sender@example.com> wrote:
+> reply with CC"
+
+test_begin_subtest "Reply from alternate address"
+add_message '[from]="Sender <sender@example.com>"' \
+ [to]=test_suite_other@notmuchmail.org \
+ [subject]=notmuch-reply-test \
+ '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
+ '[body]="reply from alternate address"'
+
+output=$(notmuch reply id:${gen_msg_id})
+test_expect_equal "$output" "From: Notmuch Test Suite <test_suite_other@notmuchmail.org>
+Subject: Re: notmuch-reply-test
+To: Sender <sender@example.com>
+In-Reply-To: <${gen_msg_id}>
+References: <${gen_msg_id}>
+
+On Tue, 05 Jan 2010 15:43:56 -0000, Sender <sender@example.com> wrote:
+> reply from alternate address"
+
+test_begin_subtest "Reply from address in named group list"
+add_message '[from]="Sender <sender@example.com>"' \
+ '[to]=group:test_suite@notmuchmail.org,someone@example.com\;' \
+ [cc]=test_suite_other@notmuchmail.org \
+ [subject]=notmuch-reply-test \
+ '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
+ '[body]="Reply from address in named group list"'
+
+output=$(notmuch reply id:${gen_msg_id})
+test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@notmuchmail.org>
+Subject: Re: notmuch-reply-test
+To: Sender <sender@example.com>, someone@example.com
+In-Reply-To: <${gen_msg_id}>
+References: <${gen_msg_id}>
+
+On Tue, 05 Jan 2010 15:43:56 -0000, Sender <sender@example.com> wrote:
+> Reply from address in named group list"
+
+test_begin_subtest "Support for Reply-To"
+add_message '[from]="Sender <sender@example.com>"' \
+ [to]=test_suite@notmuchmail.org \
+ [subject]=notmuch-reply-test \
+ '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
+ '[body]="support for reply-to"' \
+ '[reply-to]="Sender <elsewhere@example.com>"'
+
+output=$(notmuch reply id:${gen_msg_id})
+test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@notmuchmail.org>
+Subject: Re: notmuch-reply-test
+To: Sender <elsewhere@example.com>
+In-Reply-To: <${gen_msg_id}>
+References: <${gen_msg_id}>
+
+On Tue, 05 Jan 2010 15:43:56 -0000, Sender <sender@example.com> wrote:
+> support for reply-to"
+
+test_begin_subtest "Un-munging Reply-To"
+add_message '[from]="Sender <sender@example.com>"' \
+ '[to]="Some List <list@example.com>"' \
+ [subject]=notmuch-reply-test \
+ '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
+ '[body]="Un-munging Reply-To"' \
+ '[reply-to]="Evil Munging List <list@example.com>"'
+
+output=$(notmuch reply id:${gen_msg_id})
+test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@notmuchmail.org>
+Subject: Re: notmuch-reply-test
+To: Sender <sender@example.com>, Some List <list@example.com>
+In-Reply-To: <${gen_msg_id}>
+References: <${gen_msg_id}>
+
+On Tue, 05 Jan 2010 15:43:56 -0000, Sender <sender@example.com> wrote:
+> Un-munging Reply-To"
+
+test_begin_subtest "Message with header of exactly 200 bytes"
+add_message '[subject]="This subject is exactly 200 bytes in length. Other than its length there is not much of note here. Note that the length of 200 bytes includes the Subject: and Re: prefixes with two spaces"' \
+ '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
+ '[body]="200-byte header"'
+output=$(notmuch reply id:${gen_msg_id})
+test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@notmuchmail.org>
+Subject: Re: This subject is exactly 200 bytes in length. Other than its
+ length there is not much of note here. Note that the length of 200 bytes
+ includes the Subject: and Re: prefixes with two spaces
+In-Reply-To: <${gen_msg_id}>
+References: <${gen_msg_id}>
+
+On Tue, 05 Jan 2010 15:43:56 -0000, Notmuch Test Suite <test_suite@notmuchmail.org> wrote:
+> 200-byte header"
+
+test_begin_subtest "From guessing: Envelope-To"
+add_message '[from]="Sender <sender@example.com>"' \
+ '[to]="Recipient <recipient@example.com>"' \
+ '[subject]="From guessing"' \
+ '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
+ '[body]="From guessing"' \
+ '[header]="Envelope-To: test_suite_other@notmuchmail.org"'
+
+output=$(notmuch reply id:${gen_msg_id})
+test_expect_equal "$output" "From: Notmuch Test Suite <test_suite_other@notmuchmail.org>
+Subject: Re: From guessing
+To: Sender <sender@example.com>, Recipient <recipient@example.com>
+In-Reply-To: <${gen_msg_id}>
+References: <${gen_msg_id}>
+
+On Tue, 05 Jan 2010 15:43:56 -0000, Sender <sender@example.com> wrote:
+> From guessing"
+
+test_begin_subtest "From guessing: X-Original-To"
+add_message '[from]="Sender <sender@example.com>"' \
+ '[to]="Recipient <recipient@example.com>"' \
+ '[subject]="From guessing"' \
+ '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
+ '[body]="From guessing"' \
+ '[header]="X-Original-To: test_suite@otherdomain.org"'
+
+output=$(notmuch reply id:${gen_msg_id})
+test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@otherdomain.org>
+Subject: Re: From guessing
+To: Sender <sender@example.com>, Recipient <recipient@example.com>
+In-Reply-To: <${gen_msg_id}>
+References: <${gen_msg_id}>
+
+On Tue, 05 Jan 2010 15:43:56 -0000, Sender <sender@example.com> wrote:
+> From guessing"
+
+test_begin_subtest "From guessing: Delivered-To"
+add_message '[from]="Sender <sender@example.com>"' \
+ '[to]="Recipient <recipient@example.com>"' \
+ '[subject]="From guessing"' \
+ '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
+ '[body]="From guessing"' \
+ '[header]="Delivered-To: test_suite_other@notmuchmail.org"'
+
+output=$(notmuch reply id:${gen_msg_id})
+test_expect_equal "$output" "From: Notmuch Test Suite <test_suite_other@notmuchmail.org>
+Subject: Re: From guessing
+To: Sender <sender@example.com>, Recipient <recipient@example.com>
+In-Reply-To: <${gen_msg_id}>
+References: <${gen_msg_id}>
+
+On Tue, 05 Jan 2010 15:43:56 -0000, Sender <sender@example.com> wrote:
+> From guessing"
+
+test_begin_subtest "Reply with RFC 2047-encoded headers"
+add_message '[subject]="=?iso-8859-1?q?=e0=df=e7?="' \
+ '[from]="=?utf-8?q?=e2=98=83?= <snowman@example.com>"' \
+ '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
+ '[body]="Encoding"'
+
+# GMime happens to change from Q- to B-encoding. We canonicalize the
+# case of the encoding and charset because different versions of GMime
+# capitalize the encoding differently.
+output=$(notmuch reply id:${gen_msg_id} | perl -pe 's/=\?[^?]+\?[bB]\?/lc($&)/ge')
+test_expect_equal "$output" "\
+From: Notmuch Test Suite <test_suite@notmuchmail.org>
+Subject: Re: =?iso-8859-1?b?4N/n?=
+To: =?utf-8?b?4piD?= <snowman@example.com>
+In-Reply-To: <${gen_msg_id}>
+References: <${gen_msg_id}>
+
+On Tue, 05 Jan 2010 15:43:56 -0000, ☃ <snowman@example.com> wrote:
+> Encoding"
+
+test_begin_subtest "Reply with RFC 2047-encoded headers (JSON)"
+output=$(notmuch reply --format=json id:${gen_msg_id})
+test_expect_equal_json "$output" '
+{
+ "original": {
+ "body": [
+ {
+ "content": "Encoding\n",
+ "content-type": "text/plain",
+ "id": 1
+ }
+ ],
+ "date_relative": "2010-01-05",
+ "excluded": false,
+ "filename": "'${MAIL_DIR}'/msg-012",
+ "headers": {
+ "Date": "Tue, 05 Jan 2010 15:43:56 +0000",
+ "From": "\u2603 <snowman@example.com>",
+ "Subject": "\u00e0\u00df\u00e7",
+ "To": "Notmuch Test Suite <test_suite@notmuchmail.org>"
+ },
+ "id": "'${gen_msg_id}'",
+ "match": false,
+ "tags": [
+ "inbox",
+ "unread"
+ ],
+ "timestamp": 1262706236
+ },
+ "reply-headers": {
+ "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
+ "In-reply-to": "<'${gen_msg_id}'>",
+ "References": "<'${gen_msg_id}'>",
+ "Subject": "Re: \u00e0\u00df\u00e7",
+ "To": "\u2603 <snowman@example.com>"
+ }
+}'
+
+
+test_done
--- /dev/null
+#!/usr/bin/env bash
+test_description="\"notmuch reply --reply-to=sender\" in several variations"
+. ./test-lib.sh
+
+test_begin_subtest "Basic reply-to-sender"
+add_message '[from]="Sender <sender@example.com>"' \
+ [to]=test_suite@notmuchmail.org \
+ [subject]=notmuch-reply-test \
+ '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
+ '[body]="basic reply-to-sender test"'
+
+output=$(notmuch reply --reply-to=sender id:${gen_msg_id})
+test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@notmuchmail.org>
+Subject: Re: notmuch-reply-test
+To: Sender <sender@example.com>
+In-Reply-To: <${gen_msg_id}>
+References: <${gen_msg_id}>
+
+On Tue, 05 Jan 2010 15:43:56 -0000, Sender <sender@example.com> wrote:
+> basic reply-to-sender test"
+
+test_begin_subtest "From Us, Basic reply to message"
+add_message '[from]="Notmuch Test Suite <test_suite@notmuchmail.org>"' \
+ '[to]="Recipient <recipient@example.com>"' \
+ [subject]=notmuch-reply-test \
+ '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
+ '[body]="basic reply-to-from-us test"'
+
+output=$(notmuch reply --reply-to=sender id:${gen_msg_id})
+test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@notmuchmail.org>
+Subject: Re: notmuch-reply-test
+To: Recipient <recipient@example.com>
+In-Reply-To: <${gen_msg_id}>
+References: <${gen_msg_id}>
+
+On Tue, 05 Jan 2010 15:43:56 -0000, Notmuch Test Suite <test_suite@notmuchmail.org> wrote:
+> basic reply-to-from-us test"
+
+test_begin_subtest "Multiple recipients"
+add_message '[from]="Sender <sender@example.com>"' \
+ '[to]="test_suite@notmuchmail.org, Someone Else <someone@example.com>"' \
+ [subject]=notmuch-reply-test \
+ '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
+ '[body]="Multiple recipients"'
+
+output=$(notmuch reply --reply-to=sender id:${gen_msg_id})
+test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@notmuchmail.org>
+Subject: Re: notmuch-reply-test
+To: Sender <sender@example.com>
+In-Reply-To: <${gen_msg_id}>
+References: <${gen_msg_id}>
+
+On Tue, 05 Jan 2010 15:43:56 -0000, Sender <sender@example.com> wrote:
+> Multiple recipients"
+
+test_begin_subtest "From Us, Multiple TO recipients"
+add_message '[from]="Notmuch Test Suite <test_suite@notmuchmail.org>"' \
+ '[to]="Recipient <recipient@example.com>, Someone Else <someone@example.com>"' \
+ [subject]=notmuch-reply-test \
+ '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
+ '[body]="From Us, Multiple TO recipients"'
+
+output=$(notmuch reply --reply-to=sender id:${gen_msg_id})
+test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@notmuchmail.org>
+Subject: Re: notmuch-reply-test
+To: Recipient <recipient@example.com>, Someone Else <someone@example.com>
+In-Reply-To: <${gen_msg_id}>
+References: <${gen_msg_id}>
+
+On Tue, 05 Jan 2010 15:43:56 -0000, Notmuch Test Suite <test_suite@notmuchmail.org> wrote:
+> From Us, Multiple TO recipients"
+
+test_begin_subtest "Reply with CC"
+add_message '[from]="Sender <sender@example.com>"' \
+ [to]=test_suite@notmuchmail.org \
+ '[cc]="Other Parties <cc@example.com>"' \
+ [subject]=notmuch-reply-test \
+ '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
+ '[body]="reply with CC"'
+
+output=$(notmuch reply --reply-to=sender id:${gen_msg_id})
+test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@notmuchmail.org>
+Subject: Re: notmuch-reply-test
+To: Sender <sender@example.com>
+In-Reply-To: <${gen_msg_id}>
+References: <${gen_msg_id}>
+
+On Tue, 05 Jan 2010 15:43:56 -0000, Sender <sender@example.com> wrote:
+> reply with CC"
+
+test_begin_subtest "From Us, Reply with CC"
+add_message '[from]="Notmuch Test Suite <test_suite@notmuchmail.org>"' \
+ '[to]="Recipient <recipient@example.com>"' \
+ '[cc]="Other Parties <cc@example.com>"' \
+ [subject]=notmuch-reply-test \
+ '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
+ '[body]="reply with CC"'
+
+output=$(notmuch reply --reply-to=sender id:${gen_msg_id})
+test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@notmuchmail.org>
+Subject: Re: notmuch-reply-test
+To: Recipient <recipient@example.com>
+In-Reply-To: <${gen_msg_id}>
+References: <${gen_msg_id}>
+
+On Tue, 05 Jan 2010 15:43:56 -0000, Notmuch Test Suite <test_suite@notmuchmail.org> wrote:
+> reply with CC"
+
+test_begin_subtest "From Us, Reply no TO but with CC"
+add_message '[from]="Notmuch Test Suite <test_suite@notmuchmail.org>"' \
+ '[cc]="Other Parties <cc@example.com>"' \
+ [subject]=notmuch-reply-test \
+ '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
+ '[body]="reply with CC"'
+
+output=$(notmuch reply --reply-to=sender id:${gen_msg_id})
+test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@notmuchmail.org>
+Subject: Re: notmuch-reply-test
+Cc: Other Parties <cc@example.com>
+In-Reply-To: <${gen_msg_id}>
+References: <${gen_msg_id}>
+
+On Tue, 05 Jan 2010 15:43:56 -0000, Notmuch Test Suite <test_suite@notmuchmail.org> wrote:
+> reply with CC"
+
+test_begin_subtest "Reply from alternate address"
+add_message '[from]="Sender <sender@example.com>"' \
+ [to]=test_suite_other@notmuchmail.org \
+ [subject]=notmuch-reply-test \
+ '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
+ '[body]="reply from alternate address"'
+
+output=$(notmuch reply --reply-to=sender id:${gen_msg_id})
+test_expect_equal "$output" "From: Notmuch Test Suite <test_suite_other@notmuchmail.org>
+Subject: Re: notmuch-reply-test
+To: Sender <sender@example.com>
+In-Reply-To: <${gen_msg_id}>
+References: <${gen_msg_id}>
+
+On Tue, 05 Jan 2010 15:43:56 -0000, Sender <sender@example.com> wrote:
+> reply from alternate address"
+
+test_begin_subtest "Support for Reply-To"
+add_message '[from]="Sender <sender@example.com>"' \
+ [to]=test_suite@notmuchmail.org \
+ [subject]=notmuch-reply-test \
+ '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
+ '[body]="support for reply-to"' \
+ '[reply-to]="Sender <elsewhere@example.com>"'
+
+output=$(notmuch reply --reply-to=sender id:${gen_msg_id})
+test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@notmuchmail.org>
+Subject: Re: notmuch-reply-test
+To: Sender <elsewhere@example.com>
+In-Reply-To: <${gen_msg_id}>
+References: <${gen_msg_id}>
+
+On Tue, 05 Jan 2010 15:43:56 -0000, Sender <sender@example.com> wrote:
+> support for reply-to"
+
+test_begin_subtest "Support for Reply-To with multiple recipients"
+add_message '[from]="Sender <sender@example.com>"' \
+ '[to]="test_suite@notmuchmail.org, Someone Else <someone@example.com>"' \
+ [subject]=notmuch-reply-test \
+ '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
+ '[body]="support for reply-to with multiple recipients"' \
+ '[reply-to]="Sender <elsewhere@example.com>"'
+
+output=$(notmuch reply --reply-to=sender id:${gen_msg_id})
+test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@notmuchmail.org>
+Subject: Re: notmuch-reply-test
+To: Sender <elsewhere@example.com>
+In-Reply-To: <${gen_msg_id}>
+References: <${gen_msg_id}>
+
+On Tue, 05 Jan 2010 15:43:56 -0000, Sender <sender@example.com> wrote:
+> support for reply-to with multiple recipients"
+
+test_begin_subtest "Un-munging Reply-To"
+add_message '[from]="Sender <sender@example.com>"' \
+ '[to]="Some List <list@example.com>"' \
+ [subject]=notmuch-reply-test \
+ '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
+ '[body]="Un-munging Reply-To"' \
+ '[reply-to]="Evil Munging List <list@example.com>"'
+
+output=$(notmuch reply --reply-to=sender id:${gen_msg_id})
+test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@notmuchmail.org>
+Subject: Re: notmuch-reply-test
+To: Sender <sender@example.com>
+In-Reply-To: <${gen_msg_id}>
+References: <${gen_msg_id}>
+
+On Tue, 05 Jan 2010 15:43:56 -0000, Sender <sender@example.com> wrote:
+> Un-munging Reply-To"
+
+test_begin_subtest "Message with header of exactly 200 bytes"
+add_message '[subject]="This subject is exactly 200 bytes in length. Other than its length there is not much of note here. Note that the length of 200 bytes includes the Subject: and Re: prefixes with two spaces"' \
+ '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
+ '[body]="200-byte header"'
+output=$(notmuch reply --reply-to=sender id:${gen_msg_id})
+test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@notmuchmail.org>
+Subject: Re: This subject is exactly 200 bytes in length. Other than its
+ length there is not much of note here. Note that the length of 200 bytes
+ includes the Subject: and Re: prefixes with two spaces
+In-Reply-To: <${gen_msg_id}>
+References: <${gen_msg_id}>
+
+On Tue, 05 Jan 2010 15:43:56 -0000, Notmuch Test Suite <test_suite@notmuchmail.org> wrote:
+> 200-byte header"
+test_done
--- /dev/null
+#!/usr/bin/env bash
+test_description="\"notmuch dump\" and \"notmuch restore\""
+. ./test-lib.sh
+
+add_email_corpus
+
+test_expect_success 'Dumping all tags' \
+ 'generate_message &&
+ notmuch new &&
+ notmuch dump > dump.expected'
+
+# The use of from:cworth is rather arbitrary: it matches some of the
+# email corpus' messages, but not all of them.
+
+test_expect_success 'Dumping all tags II' \
+ 'notmuch tag +ABC +DEF -- from:cworth &&
+ notmuch dump > dump-ABC_DEF.expected &&
+ ! cmp dump.expected dump-ABC_DEF.expected'
+
+test_expect_success 'Clearing all tags' \
+ 'sed -e "s/(\([^(]*\))$/()/" < dump.expected > clear.expected &&
+ notmuch restore --input=clear.expected &&
+ notmuch dump > clear.actual &&
+ test_cmp clear.expected clear.actual'
+
+test_expect_success 'Accumulate original tags' \
+ 'notmuch tag +ABC +DEF -- from:cworth &&
+ notmuch restore --accumulate < dump.expected &&
+ notmuch dump > dump.actual &&
+ test_cmp dump-ABC_DEF.expected dump.actual'
+
+test_expect_success 'Restoring original tags' \
+ 'notmuch restore --input=dump.expected &&
+ notmuch dump > dump.actual &&
+ test_cmp dump.expected dump.actual'
+
+test_expect_success 'Restore with nothing to do' \
+ 'notmuch restore < dump.expected &&
+ notmuch dump > dump.actual &&
+ test_cmp dump.expected dump.actual'
+
+test_expect_success 'Accumulate with existing tags' \
+ 'notmuch restore --accumulate --input=dump.expected &&
+ notmuch dump > dump.actual &&
+ test_cmp dump.expected dump.actual'
+
+test_expect_success 'Accumulate with no tags' \
+ 'notmuch restore --accumulate < clear.expected &&
+ notmuch dump > dump.actual &&
+ test_cmp dump.expected dump.actual'
+
+test_expect_success 'Accumulate with new tags' \
+ 'notmuch restore --input=dump.expected &&
+ notmuch restore --accumulate --input=dump-ABC_DEF.expected &&
+ notmuch dump > OUTPUT.$test_count &&
+ notmuch restore --input=dump.expected &&
+ test_cmp dump-ABC_DEF.expected OUTPUT.$test_count'
+
+# notmuch restore currently only considers the first argument.
+test_expect_success 'Invalid restore invocation' \
+ 'test_must_fail notmuch restore --input=dump.expected another_one'
+
+test_begin_subtest "dump --output=outfile"
+notmuch dump --output=dump-outfile.actual
+test_expect_equal_file dump.expected dump-outfile.actual
+
+test_begin_subtest "dump --output=outfile --"
+notmuch dump --output=dump-1-arg-dash.actual --
+test_expect_equal_file dump.expected dump-1-arg-dash.actual
+
+# Note, we assume all messages from cworth have a message-id
+# containing cworth.org
+
+grep 'cworth[.]org' dump.expected > dump-cworth.expected
+
+test_begin_subtest "dump -- from:cworth"
+notmuch dump -- from:cworth > dump-dash-cworth.actual
+test_expect_equal_file dump-cworth.expected dump-dash-cworth.actual
+
+test_begin_subtest "dump --output=outfile from:cworth"
+notmuch dump --output=dump-outfile-cworth.actual from:cworth
+test_expect_equal_file dump-cworth.expected dump-outfile-cworth.actual
+
+test_begin_subtest "dump --output=outfile -- from:cworth"
+notmuch dump --output=dump-outfile-dash-inbox.actual -- from:cworth
+test_expect_equal_file dump-cworth.expected dump-outfile-dash-inbox.actual
+
+test_begin_subtest "Check for a safe set of message-ids"
+notmuch search --output=messages from:cworth | sed s/^id:// > EXPECTED
+notmuch search --output=messages from:cworth | sed s/^id:// |\
+ $TEST_DIRECTORY/hex-xcode --direction=encode > OUTPUT
+test_expect_equal_file OUTPUT EXPECTED
+
+test_begin_subtest "format=batch-tag, dump sanity check."
+notmuch dump --format=sup from:cworth | cut -f1 -d' ' | \
+ sort > EXPECTED.$test_count
+notmuch dump --format=batch-tag from:cworth | sed 's/^.*-- id://' | \
+ sort > OUTPUT.$test_count
+test_expect_equal_file EXPECTED.$test_count OUTPUT.$test_count
+
+test_begin_subtest "format=batch-tag, # round-trip"
+notmuch dump --format=sup | sort > EXPECTED.$test_count
+notmuch dump --format=batch-tag | notmuch restore --format=batch-tag
+notmuch dump --format=sup | sort > OUTPUT.$test_count
+test_expect_equal_file EXPECTED.$test_count OUTPUT.$test_count
+
+test_begin_subtest "format=batch-tag, # blank lines and comments"
+notmuch dump --format=batch-tag| sort > EXPECTED.$test_count
+notmuch restore <<EOF
+# this line is a comment; the next has only white space
+
+
+# the previous line is empty
+EOF
+notmuch dump --format=batch-tag | sort > OUTPUT.$test_count
+test_expect_equal_file EXPECTED.$test_count OUTPUT.$test_count
+
+test_begin_subtest "format=batch-tag, # reverse-round-trip empty tag"
+cat <<EOF >EXPECTED.$test_count
++ -- id:20091117232137.GA7669@griffis1.net
+EOF
+notmuch restore --format=batch-tag < EXPECTED.$test_count
+notmuch dump --format=batch-tag id:20091117232137.GA7669@griffis1.net > OUTPUT.$test_count
+test_expect_equal_file EXPECTED.$test_count OUTPUT.$test_count
+
+tag1='comic_swear=$&^%$^%\\//-+$^%$'
+enc1=$($TEST_DIRECTORY/hex-xcode --direction=encode "$tag1")
+
+tag2=$(printf 'this\n tag\t has\n spaces')
+enc2=$($TEST_DIRECTORY/hex-xcode --direction=encode "$tag2")
+
+enc3='%c3%91%c3%a5%c3%b0%c3%a3%c3%a5%c3%a9-%c3%8f%c3%8a'
+tag3=$($TEST_DIRECTORY/hex-xcode --direction=decode $enc3)
+
+notmuch dump --format=batch-tag > BACKUP
+
+notmuch tag +"$tag1" +"$tag2" +"$tag3" -inbox -unread "*"
+
+# initial segment of file used for several tests below.
+cat <<EOF > comments-and-blanks
+# this is a comment
+
+# next line has leading whitespace
+
+
+EOF
+
+test_begin_subtest 'restoring empty file is not an error'
+notmuch restore < /dev/null 2>OUTPUT.$test_count
+cp /dev/null EXPECTED
+test_expect_equal_file EXPECTED OUTPUT.$test_count
+
+test_begin_subtest 'file of comments and blank lines is not an error'
+notmuch restore --input=comments-and-blanks
+ret_val=$?
+test_expect_equal "$ret_val" "0"
+
+cp comments-and-blanks leading-comments-blanks-batch-tag
+echo "+some_tag -- id:yun1vjwegii.fsf@aiko.keithp.com" \
+ >> leading-comments-blanks-batch-tag
+
+test_begin_subtest 'detect format=batch-tag with leading comments and blanks'
+notmuch restore --input=leading-comments-blanks-batch-tag
+notmuch search --output=tags id:yun1vjwegii.fsf@aiko.keithp.com > OUTPUT.$test_count
+echo "some_tag" > EXPECTED
+test_expect_equal_file EXPECTED OUTPUT.$test_count
+
+cp comments-and-blanks leading-comments-blanks-sup
+echo "yun1vjwegii.fsf@aiko.keithp.com (another_tag)" \
+ >> leading-comments-blanks-sup
+
+test_begin_subtest 'detect format=sup with leading comments and blanks'
+notmuch restore --input=leading-comments-blanks-sup
+notmuch search --output=tags id:yun1vjwegii.fsf@aiko.keithp.com > OUTPUT.$test_count
+echo "another_tag" > EXPECTED
+test_expect_equal_file EXPECTED OUTPUT.$test_count
+
+test_begin_subtest 'format=batch-tag, round trip with strange tags'
+notmuch dump --format=batch-tag > EXPECTED.$test_count
+notmuch dump --format=batch-tag | notmuch restore --format=batch-tag
+notmuch dump --format=batch-tag > OUTPUT.$test_count
+test_expect_equal_file EXPECTED.$test_count OUTPUT.$test_count
+
+test_begin_subtest 'format=batch-tag, checking encoded output'
+notmuch dump --format=batch-tag -- from:cworth |\
+ awk "{ print \"+$enc1 +$enc2 +$enc3 -- \" \$5 }" > EXPECTED.$test_count
+notmuch dump --format=batch-tag -- from:cworth > OUTPUT.$test_count
+test_expect_equal_file EXPECTED.$test_count OUTPUT.$test_count
+
+test_begin_subtest 'restoring sane tags'
+notmuch restore --format=batch-tag < BACKUP
+notmuch dump --format=batch-tag > OUTPUT.$test_count
+test_expect_equal_file BACKUP OUTPUT.$test_count
+
+test_begin_subtest 'format=batch-tag, restore=auto'
+notmuch dump --format=batch-tag > EXPECTED.$test_count
+notmuch tag -inbox -unread "*"
+notmuch restore --format=auto < EXPECTED.$test_count
+notmuch dump --format=batch-tag > OUTPUT.$test_count
+test_expect_equal_file EXPECTED.$test_count OUTPUT.$test_count
+
+test_begin_subtest 'format=sup, restore=auto'
+notmuch dump --format=sup > EXPECTED.$test_count
+notmuch tag -inbox -unread "*"
+notmuch restore --format=auto < EXPECTED.$test_count
+notmuch dump --format=sup > OUTPUT.$test_count
+test_expect_equal_file EXPECTED.$test_count OUTPUT.$test_count
+
+test_begin_subtest 'format=batch-tag, restore=default'
+notmuch dump --format=batch-tag > EXPECTED.$test_count
+notmuch tag -inbox -unread "*"
+notmuch restore < EXPECTED.$test_count
+notmuch dump --format=batch-tag > OUTPUT.$test_count
+test_expect_equal_file EXPECTED.$test_count OUTPUT.$test_count
+
+test_begin_subtest 'format=sup, restore=default'
+notmuch dump --format=sup > EXPECTED.$test_count
+notmuch tag -inbox -unread "*"
+notmuch restore < EXPECTED.$test_count
+notmuch dump --format=sup > OUTPUT.$test_count
+test_expect_equal_file EXPECTED.$test_count OUTPUT.$test_count
+
+test_begin_subtest 'restore: checking error messages'
+notmuch restore <<EOF 2>OUTPUT
+# the next line has a space
+
+a
++0
++a +b
+# trailing whitespace
++a +b
++c +d --
+# this is a harmless comment, do not yell about it.
+
+# the previous line was blank; also no yelling please
++%zz -- id:whatever
++e +f id:"
++e +f tag:abc
+# the next non-comment line should report an an empty tag error for
+# batch tagging, but not for restore
++ +e -- id:20091117232137.GA7669@griffis1.net
+# valid id, but warning about missing message
++e id:missing_message_id
+# exercise parser
++e -- id:some)stuff
++e -- id:some stuff
++e -- id:some"stuff
++e -- id:"a_message_id_with""_a_quote"
++e -- id:"a message id with spaces"
++e -- id:an_id_with_leading_and_trailing_ws \
+
+EOF
+
+cat <<EOF > EXPECTED
+Warning: cannot parse query: a (skipping)
+Warning: no query string [+0]
+Warning: no query string [+a +b]
+Warning: missing query string [+a +b ]
+Warning: no query string after -- [+c +d --]
+Warning: hex decoding of tag %zz failed [+%zz -- id:whatever]
+Warning: cannot parse query: id:" (skipping)
+Warning: not an id query: tag:abc (skipping)
+Warning: cannot apply tags to missing message: missing_message_id
+Warning: cannot parse query: id:some)stuff (skipping)
+Warning: cannot parse query: id:some stuff (skipping)
+Warning: cannot apply tags to missing message: some"stuff
+Warning: cannot apply tags to missing message: a_message_id_with"_a_quote
+Warning: cannot apply tags to missing message: a message id with spaces
+Warning: cannot apply tags to missing message: an_id_with_leading_and_trailing_ws
+EOF
+
+test_expect_equal_file EXPECTED OUTPUT
+
+test_begin_subtest 'roundtripping random message-ids and tags'
+
+ ${TEST_DIRECTORY}/random-corpus --config-path=${NOTMUCH_CONFIG} \
+ --num-messages=100
+
+ notmuch dump --format=batch-tag| \
+ sort > EXPECTED.$test_count
+
+ notmuch tag +this_tag_is_very_unlikely_to_be_random '*'
+
+ notmuch restore --format=batch-tag < EXPECTED.$test_count
+
+ notmuch dump --format=batch-tag| \
+ sort > OUTPUT.$test_count
+
+test_expect_equal_file EXPECTED.$test_count OUTPUT.$test_count
+
+test_done
+
+# Note the database is "poisoned" for sup format at this point.
--- /dev/null
+#!/usr/bin/env bash
+test_description="handling of uuencoded data"
+. ./test-lib.sh
+
+add_message [subject]=uuencodetest '[date]="Sat, 01 Jan 2000 12:00:00 -0000"' \
+'[body]="This message is used to ensure that notmuch correctly handles a
+message containing a block of uuencoded data. First, we have a marker
+this content beforeuudata . Then we begin the uuencoded data itself:
+
+begin 644 bogus-uuencoded-data
+M0123456789012345678901234567890123456789012345678901234567890
+MOBVIOUSLY, THIS IS NOT ANY SORT OF USEFUL UUENCODED DATA.
+MINSTEAD THIS IS JUST A WAY TO ENSURE THAT THIS BLOCK OF DATA
+MIS CORRECTLY IGNORED WHEN NOTMUCH CREATES ITS INDEX. SO WE
+MINCLUDE A DURINGUUDATA MARKER THAT SHOULD NOT RESULT IN ANY
+MSEARCH RESULT.
+\\\`
+end
+
+Finally, we have our afteruudata marker as well."'
+
+test_begin_subtest "Ensure content before uu data is indexed"
+output=$(notmuch search beforeuudata | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; uuencodetest (inbox unread)"
+
+test_begin_subtest "Ensure uu data is not indexed"
+output=$(notmuch search DURINGUUDATA | notmuch_search_sanitize)
+test_expect_equal "$output" ""
+
+test_begin_subtest "Ensure content after uu data is indexed"
+output=$(notmuch search afteruudata | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; uuencodetest (inbox unread)"
+
+test_done
--- /dev/null
+#!/usr/bin/env bash
+test_description="threading when messages received out of order"
+. ./test-lib.sh
+
+test_begin_subtest "Adding initial child message"
+generate_message [body]=foo "[in-reply-to]=\<parent-id\>" [subject]=brokenthreadtest '[date]="Sat, 01 Jan 2000 12:00:00 -0000"'
+output=$(NOTMUCH_NEW)
+test_expect_equal "$output" "Added 1 new message to the database."
+
+test_begin_subtest "Searching returns the message"
+output=$(notmuch search foo | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; brokenthreadtest (inbox unread)"
+
+test_begin_subtest "Adding second child message"
+generate_message [body]=foo "[in-reply-to]=\<parent-id\>" [subject]=brokenthreadtest '[date]="Sat, 01 Jan 2000 12:00:00 -0000"'
+output=$(NOTMUCH_NEW)
+test_expect_equal "$output" "Added 1 new message to the database."
+
+test_begin_subtest "Searching returns both messages in one thread"
+output=$(notmuch search foo | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2000-01-01 [2/2] Notmuch Test Suite; brokenthreadtest (inbox unread)"
+
+test_begin_subtest "Adding parent message"
+generate_message [body]=foo [id]=parent-id [subject]=brokenthreadtest '[date]="Sat, 01 Jan 2000 12:00:00 -0000"'
+output=$(NOTMUCH_NEW)
+test_expect_equal "$output" "Added 1 new message to the database."
+
+test_begin_subtest "Searching returns all three messages in one thread"
+output=$(notmuch search foo | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2000-01-01 [3/3] Notmuch Test Suite; brokenthreadtest (inbox unread)"
+
+test_done
--- /dev/null
+#!/usr/bin/env bash
+test_description="author reordering;"
+. ./test-lib.sh
+
+test_begin_subtest "Adding parent message"
+generate_message [body]=findme [id]=new-parent-id [subject]=author-reorder-threadtest '[from]="User <user@example.com>"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"'
+output=$(NOTMUCH_NEW)
+test_expect_equal "$output" "Added 1 new message to the database."
+
+test_begin_subtest "Adding initial child message"
+generate_message [body]=findme "[in-reply-to]=\<new-parent-id\>" [subject]=author-reorder-threadtest '[from]="User1 <user1@example.com>"' '[date]="Sat, 01 Jan 2000 12:01:00 -0000"'
+output=$(NOTMUCH_NEW)
+test_expect_equal "$output" "Added 1 new message to the database."
+
+test_begin_subtest "Adding second child message"
+generate_message [body]=findme "[in-reply-to]=\<new-parent-id\>" [subject]=author-reorder-threadtest '[from]="User2 <user2@example.com>"' '[date]="Sat, 01 Jan 2000 12:02:00 -0000"'
+output=$(NOTMUCH_NEW)
+test_expect_equal "$output" "Added 1 new message to the database."
+
+test_begin_subtest "Searching when all three messages match"
+output=$(notmuch search findme | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2000-01-01 [3/3] User, User1, User2; author-reorder-threadtest (inbox unread)"
+
+test_begin_subtest "Searching when two messages match"
+output=$(notmuch search User1 or User2 | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2000-01-01 [2/3] User1, User2| User; author-reorder-threadtest (inbox unread)"
+
+test_begin_subtest "Searching when only one message matches"
+output=$(notmuch search User2 | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2000-01-01 [1/3] User2| User, User1; author-reorder-threadtest (inbox unread)"
+
+test_begin_subtest "Searching when only first message matches"
+output=$(notmuch search User | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2000-01-01 [1/3] User| User1, User2; author-reorder-threadtest (inbox unread)"
+
+test_begin_subtest "Adding duplicate author"
+generate_message [body]=findme "[in-reply-to]=\<new-parent-id\>" [subject]=author-reorder-threadtest '[from]="User1 <user1@example.com>"' '[date]="Sat, 01 Jan 2000 12:03:00 -0000"'
+output=$(NOTMUCH_NEW)
+test_expect_equal "$output" "Added 1 new message to the database."
+
+test_begin_subtest "Searching when all four messages match"
+output=$(notmuch search findme | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2000-01-01 [4/4] User, User1, User2; author-reorder-threadtest (inbox unread)"
+
+test_begin_subtest "Adding non-monotonic child message"
+generate_message [body]=findme "[in-reply-to]=\<new-parent-id\>" [subject]=author-reorder-threadtest '[from]="User0 <user0@example.com>"' '[date]="Sat, 01 Jan 2000 11:00:00 -0000"'
+output=$(NOTMUCH_NEW)
+test_expect_equal "$output" "Added 1 new message to the database."
+
+test_begin_subtest "Searching non-monotonic messages (oldest-first)"
+output=$(notmuch search --sort=oldest-first findme | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2000-01-01 [5/5] User0, User, User1, User2; author-reorder-threadtest (inbox unread)"
+
+test_begin_subtest "Searching non-monotonic messages (newest-first)"
+output=$(notmuch search --sort=newest-first findme | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2000-01-01 [5/5] User0, User, User1, User2; author-reorder-threadtest (inbox unread)"
+
+test_done
--- /dev/null
+#!/usr/bin/env bash
+test_description="From line heuristics (with multiple configured addresses)"
+. ./test-lib.sh
+
+test_begin_subtest "Magic from guessing (nothing to go on)"
+add_message '[from]="Sender <sender@example.com>"' \
+ [to]=mailinglist@notmuchmail.org \
+ [subject]=notmuch-reply-test \
+ '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
+ '[body]="from guessing test"'
+
+output=$(notmuch reply id:${gen_msg_id})
+test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@notmuchmail.org>
+Subject: Re: notmuch-reply-test
+To: Sender <sender@example.com>, mailinglist@notmuchmail.org
+In-Reply-To: <${gen_msg_id}>
+References: <${gen_msg_id}>
+
+On Tue, 05 Jan 2010 15:43:56 -0000, Sender <sender@example.com> wrote:
+> from guessing test"
+
+test_begin_subtest "Magic from guessing (Envelope-to:)"
+add_message '[from]="Sender <sender@example.com>"' \
+ [to]=mailinglist@notmuchmail.org \
+ [subject]=notmuch-reply-test \
+ '[header]="Envelope-To: test_suite_other@notmuchmail.org"' \
+ '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
+ '[body]="from guessing test"'
+
+output=$(notmuch reply id:${gen_msg_id})
+test_expect_equal "$output" "From: Notmuch Test Suite <test_suite_other@notmuchmail.org>
+Subject: Re: notmuch-reply-test
+To: Sender <sender@example.com>, mailinglist@notmuchmail.org
+In-Reply-To: <${gen_msg_id}>
+References: <${gen_msg_id}>
+
+On Tue, 05 Jan 2010 15:43:56 -0000, Sender <sender@example.com> wrote:
+> from guessing test"
+
+test_begin_subtest "Magic from guessing (X-Original-To:)"
+add_message '[from]="Sender <sender@example.com>"' \
+ [to]=mailinglist@notmuchmail.org \
+ [subject]=notmuch-reply-test \
+ '[header]="X-Original-To: test_suite_other@notmuchmail.org"' \
+ '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
+ '[body]="from guessing test"'
+
+output=$(notmuch reply id:${gen_msg_id})
+test_expect_equal "$output" "From: Notmuch Test Suite <test_suite_other@notmuchmail.org>
+Subject: Re: notmuch-reply-test
+To: Sender <sender@example.com>, mailinglist@notmuchmail.org
+In-Reply-To: <${gen_msg_id}>
+References: <${gen_msg_id}>
+
+On Tue, 05 Jan 2010 15:43:56 -0000, Sender <sender@example.com> wrote:
+> from guessing test"
+
+test_begin_subtest "Magic from guessing (Received: .. for ..)"
+add_message '[from]="Sender <sender@example.com>"' \
+ [to]=mailinglist@notmuchmail.org \
+ [subject]=notmuch-reply-test \
+ "[header]=\"Received: from mail.example.com (mail.example.com [1.1.1.1])
+ by mail.notmuchmail.org (some MTA) with ESMTP id 12345678
+ for <test_suite_other@notmuchmail.org>; Sat, 10 Apr 2010 07:54:51 -0400 (EDT)\"" \
+ '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
+ '[body]="from guessing test"'
+
+output=$(notmuch reply id:${gen_msg_id})
+test_expect_equal "$output" "From: Notmuch Test Suite <test_suite_other@notmuchmail.org>
+Subject: Re: notmuch-reply-test
+To: Sender <sender@example.com>, mailinglist@notmuchmail.org
+In-Reply-To: <${gen_msg_id}>
+References: <${gen_msg_id}>
+
+On Tue, 05 Jan 2010 15:43:56 -0000, Sender <sender@example.com> wrote:
+> from guessing test"
+
+test_begin_subtest "Magic from guessing (Received: domain)"
+add_message '[from]="Sender <sender@example.com>"' \
+ [to]=mailinglist@notmuchmail.org \
+ [subject]=notmuch-reply-test \
+ "[header]=\"Received: from mail.example.com (mail.example.com [1.1.1.1])
+ by mail.otherdomain.org (some MTA) with ESMTP id 12345678
+ Sat, 10 Apr 2010 07:54:51 -0400 (EDT)\"" \
+ '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
+ '[body]="from guessing test"'
+
+output=$(notmuch reply id:${gen_msg_id})
+test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@otherdomain.org>
+Subject: Re: notmuch-reply-test
+To: Sender <sender@example.com>, mailinglist@notmuchmail.org
+In-Reply-To: <${gen_msg_id}>
+References: <${gen_msg_id}>
+
+On Tue, 05 Jan 2010 15:43:56 -0000, Sender <sender@example.com> wrote:
+> from guessing test"
+
+test_begin_subtest "Magic from guessing (multiple Received: headers)"
+add_message '[from]="Sender <sender@example.com>"' \
+ [to]=mailinglist@notmuchmail.org \
+ [subject]=notmuch-reply-test \
+ "[header]=\"Received: from extraneous.example.com (extraneous.example.com [1.1.1.1])
+Received: from mail.example.com (mail.example.com [1.1.1.1])
+ by mail.otherdomain.org (some MTA) with ESMTP id 12345678
+ for <test_suite_other@notmuchmail.org>; Sat, 10 Apr 2010 07:54:51 -0400 (EDT)
+Received: from extraneous.example.com (extraneous.example.com [1.1.1.1])\"" \
+ '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
+ '[body]="from guessing test"'
+
+output="$(notmuch reply id:${gen_msg_id})"
+test_expect_equal "$output" "From: Notmuch Test Suite <test_suite_other@notmuchmail.org>
+Subject: Re: notmuch-reply-test
+To: Sender <sender@example.com>, mailinglist@notmuchmail.org
+In-Reply-To: <${gen_msg_id}>
+References: <${gen_msg_id}>
+
+On Tue, 05 Jan 2010 15:43:56 -0000, Sender <sender@example.com> wrote:
+> from guessing test"
+
+test_begin_subtest "Testing From line heuristics (with single configured address)"
+sed -i -e "s/^other_email.*//" "${NOTMUCH_CONFIG}"
+test_expect_equal '' ''
+
+test_begin_subtest "Magic from guessing (nothing to go on)"
+add_message '[from]="Sender <sender@example.com>"' \
+ [to]=mailinglist@notmuchmail.org \
+ [subject]=notmuch-reply-test \
+ '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
+ '[body]="from guessing test"'
+
+output=$(notmuch reply id:${gen_msg_id})
+test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@notmuchmail.org>
+Subject: Re: notmuch-reply-test
+To: Sender <sender@example.com>, mailinglist@notmuchmail.org
+In-Reply-To: <${gen_msg_id}>
+References: <${gen_msg_id}>
+
+On Tue, 05 Jan 2010 15:43:56 -0000, Sender <sender@example.com> wrote:
+> from guessing test"
+
+test_begin_subtest "Magic from guessing (Envelope-to:)"
+add_message '[from]="Sender <sender@example.com>"' \
+ [to]=mailinglist@notmuchmail.org \
+ [subject]=notmuch-reply-test \
+ '[header]="Envelope-To: test_suite_other@notmuchmail.org"' \
+ '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
+ '[body]="from guessing test"'
+
+output=$(notmuch reply id:${gen_msg_id})
+test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@notmuchmail.org>
+Subject: Re: notmuch-reply-test
+To: Sender <sender@example.com>, mailinglist@notmuchmail.org
+In-Reply-To: <${gen_msg_id}>
+References: <${gen_msg_id}>
+
+On Tue, 05 Jan 2010 15:43:56 -0000, Sender <sender@example.com> wrote:
+> from guessing test"
+
+test_begin_subtest "Magic from guessing (X-Original-To:)"
+add_message '[from]="Sender <sender@example.com>"' \
+ [to]=mailinglist@notmuchmail.org \
+ [subject]=notmuch-reply-test \
+ '[header]="X-Original-To: test_suite_other@notmuchmail.org"' \
+ '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
+ '[body]="from guessing test"'
+
+output=$(notmuch reply id:${gen_msg_id})
+test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@notmuchmail.org>
+Subject: Re: notmuch-reply-test
+To: Sender <sender@example.com>, mailinglist@notmuchmail.org
+In-Reply-To: <${gen_msg_id}>
+References: <${gen_msg_id}>
+
+On Tue, 05 Jan 2010 15:43:56 -0000, Sender <sender@example.com> wrote:
+> from guessing test"
+
+test_begin_subtest "Magic from guessing (Received: .. for ..)"
+add_message '[from]="Sender <sender@example.com>"' \
+ [to]=mailinglist@notmuchmail.org \
+ [subject]=notmuch-reply-test \
+ "[header]=\"Received: from mail.example.com (mail.example.com [1.1.1.1])
+ by mail.notmuchmail.org (some MTA) with ESMTP id 12345678
+ for <test_suite_other@notmuchmail.org>; Sat, 10 Apr 2010 07:54:51 -0400 (EDT)\"" \
+ '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
+ '[body]="from guessing test"'
+
+output=$(notmuch reply id:${gen_msg_id})
+test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@notmuchmail.org>
+Subject: Re: notmuch-reply-test
+To: Sender <sender@example.com>, mailinglist@notmuchmail.org
+In-Reply-To: <${gen_msg_id}>
+References: <${gen_msg_id}>
+
+On Tue, 05 Jan 2010 15:43:56 -0000, Sender <sender@example.com> wrote:
+> from guessing test"
+
+test_begin_subtest "Magic from guessing (Received: domain)"
+add_message '[from]="Sender <sender@example.com>"' \
+ [to]=mailinglist@notmuchmail.org \
+ [subject]=notmuch-reply-test \
+ "[header]=\"Received: from mail.example.com (mail.example.com [1.1.1.1])
+ by mail.otherdomain.org (some MTA) with ESMTP id 12345678
+ Sat, 10 Apr 2010 07:54:51 -0400 (EDT)\"" \
+ '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
+ '[body]="from guessing test"'
+
+output=$(notmuch reply id:${gen_msg_id})
+test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@notmuchmail.org>
+Subject: Re: notmuch-reply-test
+To: Sender <sender@example.com>, mailinglist@notmuchmail.org
+In-Reply-To: <${gen_msg_id}>
+References: <${gen_msg_id}>
+
+On Tue, 05 Jan 2010 15:43:56 -0000, Sender <sender@example.com> wrote:
+> from guessing test"
+
+test_done
--- /dev/null
+#!/usr/bin/env bash
+test_description="messages with ridiculously-long message IDs"
+. ./test-lib.sh
+
+test_begin_subtest "Referencing long ID before adding"
+generate_message '[subject]="Reference of ridiculously-long message ID"' \
+ "[references]=\<abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-\>"
+output=$(NOTMUCH_NEW)
+test_expect_equal "$output" "Added 1 new message to the database."
+
+test_begin_subtest "Adding message with long ID"
+generate_message '[subject]="A ridiculously-long message ID"' \
+ "[id]=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-"
+output=$(NOTMUCH_NEW)
+test_expect_equal "$output" "Added 1 new message to the database."
+
+test_begin_subtest "Referencing long ID after adding"
+generate_message '[subject]="Reply to ridiculously-long message ID"' \
+ "[in-reply-to]=\<abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-\>"
+output=$(NOTMUCH_NEW)
+test_expect_equal "$output" "Added 1 new message to the database."
+
+test_begin_subtest "Ensure all messages were threaded together"
+output=$(notmuch search 'subject:"a ridiculously-long message ID"' | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2001-01-05 [1/3] Notmuch Test Suite; A ridiculously-long message ID (inbox unread)"
+
+test_done
--- /dev/null
+#!/usr/bin/env bash
+test_description="encoding issues"
+. ./test-lib.sh
+
+test_begin_subtest "Message with text of unknown charset"
+add_message '[content-type]="text/plain; charset=unknown-8bit"' \
+ "[body]=irrelevant"
+output=$(notmuch show id:${gen_msg_id} 2>&1 | notmuch_show_sanitize_all)
+test_expect_equal "$output" "\fmessage{ id:XXXXX depth:0 match:1 excluded:0 filename:XXXXX
+\fheader{
+Notmuch Test Suite <test_suite@notmuchmail.org> (2001-01-05) (inbox unread)
+Subject: Message with text of unknown charset
+From: Notmuch Test Suite <test_suite@notmuchmail.org>
+To: Notmuch Test Suite <test_suite@notmuchmail.org>
+Date: GENERATED_DATE
+\fheader}
+\fbody{
+\fpart{ ID: 1, Content-type: text/plain
+irrelevant
+\fpart}
+\fbody}
+\fmessage}"
+
+test_begin_subtest "Search for ISO-8859-2 encoded message"
+add_message '[content-type]="text/plain; charset=iso-8859-2"' \
+ '[content-transfer-encoding]=8bit' \
+ '[subject]="ISO-8859-2 encoded message"' \
+ "[body]=$'Czech word tu\350\362\341\350\350\355 means pinguin\'s.'" # ISO-8859-2 characters are generated by shell's escape sequences
+output=$(notmuch search tučňáččí 2>&1 | notmuch_show_sanitize_all)
+test_expect_equal "$output" "thread:0000000000000002 2001-01-05 [1/1] Notmuch Test Suite; ISO-8859-2 encoded message (inbox unread)"
+
+test_begin_subtest "RFC 2047 encoded word with spaces"
+add_message '[subject]="=?utf-8?q?encoded word with spaces?="'
+output=$(notmuch search id:${gen_msg_id} 2>&1 | notmuch_show_sanitize)
+test_expect_equal "$output" "thread:0000000000000003 2001-01-05 [1/1] Notmuch Test Suite; encoded word with spaces (inbox unread)"
+
+test_begin_subtest "RFC 2047 encoded words back to back"
+add_message '[subject]="=?utf-8?q?encoded-words-back?==?utf-8?q?to-back?="'
+output=$(notmuch search id:${gen_msg_id} 2>&1 | notmuch_show_sanitize)
+test_expect_equal "$output" "thread:0000000000000004 2001-01-05 [1/1] Notmuch Test Suite; encoded-words-backto-back (inbox unread)"
+
+test_begin_subtest "RFC 2047 encoded words without space before or after"
+add_message '[subject]="=?utf-8?q?encoded?=word without=?utf-8?q?space?=" '
+output=$(notmuch search id:${gen_msg_id} 2>&1 | notmuch_show_sanitize)
+test_expect_equal "$output" "thread:0000000000000005 2001-01-05 [1/1] Notmuch Test Suite; encodedword withoutspace (inbox unread)"
+
+test_done
--- /dev/null
+#!/usr/bin/env bash
+
+test_description="emacs interface"
+. ./test-lib.sh
+
+EXPECTED=$TEST_DIRECTORY/emacs.expected-output
+
+add_email_corpus
+
+# syntax errors in test-lib.el cause mysterious failures
+test_expect_success 'Syntax of emacs test library' \
+ "${TEST_EMACS} -Q --batch --load $TEST_DIRECTORY/test-lib.el"
+
+test_begin_subtest "Basic notmuch-hello view in emacs"
+test_emacs '(notmuch-hello)
+ (test-output)'
+test_expect_equal_file OUTPUT $EXPECTED/notmuch-hello
+
+test_begin_subtest "Saved search with 0 results"
+test_emacs '(let ((notmuch-show-empty-saved-searches t)
+ (notmuch-saved-searches
+ '\''(("inbox" . "tag:inbox")
+ ("unread" . "tag:unread")
+ ("empty" . "tag:doesnotexist"))))
+ (notmuch-hello)
+ (test-output))'
+test_expect_equal_file OUTPUT $EXPECTED/notmuch-hello-with-empty
+
+test_begin_subtest "No saved searches displayed (all with 0 results)"
+test_emacs '(let ((notmuch-saved-searches
+ '\''(("empty" . "tag:doesnotexist"))))
+ (notmuch-hello)
+ (test-output))'
+test_expect_equal_file OUTPUT $EXPECTED/notmuch-hello-no-saved-searches
+
+test_begin_subtest "Basic notmuch-search view in emacs"
+test_emacs '(notmuch-search "tag:inbox")
+ (notmuch-test-wait)
+ (test-output)'
+test_expect_equal_file OUTPUT $EXPECTED/notmuch-search-tag-inbox
+
+test_begin_subtest "Incremental parsing of search results"
+test_emacs "(ad-enable-advice 'notmuch-search-process-filter 'around 'pessimal)
+ (ad-activate 'notmuch-search-process-filter)
+ (notmuch-search \"tag:inbox\")
+ (notmuch-test-wait)
+ (ad-disable-advice 'notmuch-search-process-filter 'around 'pessimal)
+ (ad-activate 'notmuch-search-process-filter)
+ (test-output)"
+test_expect_equal_file OUTPUT $EXPECTED/notmuch-search-tag-inbox
+
+test_begin_subtest "Navigation of notmuch-hello to search results"
+test_emacs '(notmuch-hello)
+ (goto-char (point-min))
+ (re-search-forward "inbox")
+ (widget-button-press (1- (point)))
+ (notmuch-test-wait)
+ (test-output)'
+test_expect_equal_file OUTPUT $EXPECTED/notmuch-hello-view-inbox
+
+test_begin_subtest "Basic notmuch-show view in emacs"
+maildir_storage_thread=$(notmuch search --output=threads id:20091117190054.GU3165@dottiness.seas.harvard.edu)
+test_emacs "(notmuch-show \"$maildir_storage_thread\")
+ (test-output)"
+test_expect_equal_file OUTPUT $EXPECTED/notmuch-show-thread-maildir-storage
+
+test_begin_subtest "Basic notmuch-show view in emacs default indentation"
+maildir_storage_thread=$(notmuch search --output=threads id:20091117190054.GU3165@dottiness.seas.harvard.edu)
+test_emacs "(let ((notmuch-show-indent-messages-width 1))
+ (notmuch-show \"$maildir_storage_thread\")
+ (test-output))"
+test_expect_equal_file OUTPUT $EXPECTED/notmuch-show-thread-maildir-storage
+
+test_begin_subtest "Basic notmuch-show view in emacs without indentation"
+maildir_storage_thread=$(notmuch search --output=threads id:20091117190054.GU3165@dottiness.seas.harvard.edu)
+test_emacs "(let ((notmuch-show-indent-messages-width 0))
+ (notmuch-show \"$maildir_storage_thread\")
+ (test-output))"
+test_expect_equal_file OUTPUT $EXPECTED/notmuch-show-thread-maildir-storage-without-indentation
+
+test_begin_subtest "Basic notmuch-show view in emacs with fourfold indentation"
+maildir_storage_thread=$(notmuch search --output=threads id:20091117190054.GU3165@dottiness.seas.harvard.edu)
+test_emacs "(let ((notmuch-show-indent-messages-width 4))
+ (notmuch-show \"$maildir_storage_thread\")
+ (test-output))"
+test_expect_equal_file OUTPUT $EXPECTED/notmuch-show-thread-maildir-storage-with-fourfold-indentation
+
+test_begin_subtest "notmuch-show for message with invalid From"
+add_message "[subject]=\"message-with-invalid-from\"" \
+ "[from]=\"\\\"Invalid \\\" From\\\" <test_suite@notmuchmail.org>\""
+thread=$(notmuch search --output=threads subject:message-with-invalid-from)
+test_emacs "(notmuch-show \"$thread\")
+ (test-output \"OUTPUT.raw\")"
+cat <<EOF >EXPECTED
+"Invalid " (2001-01-05) (inbox)
+Subject: message-with-invalid-from
+To: Notmuch Test Suite <test_suite@notmuchmail.org>
+Date: GENERATED_DATE
+
+This is just a test message (#1)
+EOF
+notmuch_date_sanitize < OUTPUT.raw > OUTPUT
+test_expect_equal_file OUTPUT EXPECTED
+
+test_begin_subtest "Navigation of notmuch-search to thread view"
+test_emacs '(notmuch-search "tag:inbox")
+ (notmuch-test-wait)
+ (goto-char (point-min))
+ (re-search-forward "Working with Maildir")
+ (notmuch-search-show-thread)
+ (notmuch-test-wait)
+ (test-output)'
+test_expect_equal_file OUTPUT $EXPECTED/notmuch-show-thread-maildir-storage
+
+test_begin_subtest "Add tag from search view"
+os_x_darwin_thread=$(notmuch search --output=threads id:ddd65cda0911171950o4eea4389v86de9525e46052d3@mail.gmail.com)
+test_emacs "(notmuch-search \"$os_x_darwin_thread\")
+ (notmuch-test-wait)
+ (execute-kbd-macro \"+tag-from-search-view\")"
+output=$(notmuch search $os_x_darwin_thread | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2009-11-18 [4/4] Jjgod Jiang, Alexander Botero-Lowry; [notmuch] Mac OS X/Darwin compatibility issues (inbox tag-from-search-view unread)"
+
+test_begin_subtest "Remove tag from search view"
+test_emacs "(notmuch-search \"$os_x_darwin_thread\")
+ (notmuch-test-wait)
+ (execute-kbd-macro \"-tag-from-search-view\")"
+output=$(notmuch search $os_x_darwin_thread | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2009-11-18 [4/4] Jjgod Jiang, Alexander Botero-Lowry; [notmuch] Mac OS X/Darwin compatibility issues (inbox unread)"
+
+test_begin_subtest "Add tag (large query)"
+# We use a long query to force us into batch mode and use a funny tag
+# that requires escaping for batch tagging.
+test_emacs "(notmuch-tag (concat \"$os_x_darwin_thread\" \" or \" (make-string notmuch-tag-argument-limit ?x)) (list \"+tag-from-%-large-query\"))"
+output=$(notmuch search $os_x_darwin_thread | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2009-11-18 [4/4] Jjgod Jiang, Alexander Botero-Lowry; [notmuch] Mac OS X/Darwin compatibility issues (inbox tag-from-%-large-query unread)"
+notmuch tag -tag-from-%-large-query $os_x_darwin_thread
+
+test_begin_subtest "notmuch-show: add single tag to single message"
+test_emacs "(notmuch-show \"$os_x_darwin_thread\")
+ (execute-kbd-macro \"+tag-from-show-view\")"
+output=$(notmuch search $os_x_darwin_thread | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2009-11-18 [4/4] Jjgod Jiang, Alexander Botero-Lowry; [notmuch] Mac OS X/Darwin compatibility issues (inbox tag-from-show-view unread)"
+
+test_begin_subtest "notmuch-show: remove single tag from single message"
+test_emacs "(notmuch-show \"$os_x_darwin_thread\")
+ (execute-kbd-macro \"-tag-from-show-view\")"
+output=$(notmuch search $os_x_darwin_thread | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2009-11-18 [4/4] Jjgod Jiang, Alexander Botero-Lowry; [notmuch] Mac OS X/Darwin compatibility issues (inbox unread)"
+
+test_begin_subtest "notmuch-show: add multiple tags to single message"
+test_emacs "(notmuch-show \"$os_x_darwin_thread\")
+ (execute-kbd-macro \"+tag1-from-show-view +tag2-from-show-view\")"
+output=$(notmuch search $os_x_darwin_thread | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2009-11-18 [4/4] Jjgod Jiang, Alexander Botero-Lowry; [notmuch] Mac OS X/Darwin compatibility issues (inbox tag1-from-show-view tag2-from-show-view unread)"
+
+test_begin_subtest "notmuch-show: remove multiple tags from single message"
+test_emacs "(notmuch-show \"$os_x_darwin_thread\")
+ (execute-kbd-macro \"-tag1-from-show-view -tag2-from-show-view\")"
+output=$(notmuch search $os_x_darwin_thread | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2009-11-18 [4/4] Jjgod Jiang, Alexander Botero-Lowry; [notmuch] Mac OS X/Darwin compatibility issues (inbox unread)"
+
+test_begin_subtest "Message with .. in Message-Id:"
+add_message [id]=123..456@example '[subject]="Message with .. in Message-Id"'
+test_emacs '(notmuch-search "id:\"123..456@example\"")
+ (notmuch-test-wait)
+ (execute-kbd-macro "+search-add")
+ (execute-kbd-macro "+search-remove")
+ (execute-kbd-macro "-search-remove")
+ (notmuch-show "id:\"123..456@example\"")
+ (notmuch-test-wait)
+ (execute-kbd-macro "+show-add")
+ (execute-kbd-macro "+show-remove")
+ (execute-kbd-macro "-show-remove")'
+output=$(notmuch search 'id:"123..456@example"' | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Message with .. in Message-Id (inbox search-add show-add)"
+
+test_begin_subtest "Message with quote in Message-Id:"
+add_message '[id]="\"quote\"@example"' '[subject]="Message with quote in Message-Id"'
+test_emacs '(notmuch-search "subject:\"Message with quote\"")
+ (notmuch-test-wait)
+ (execute-kbd-macro "+search-add")
+ (notmuch-search-show-thread)
+ (notmuch-test-wait)
+ (execute-kbd-macro "+show-add")'
+output=$(notmuch search 'id:"""quote""@example"' | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Message with quote in Message-Id (inbox search-add show-add)"
+
+test_begin_subtest "Sending a message via (fake) SMTP"
+emacs_deliver_message \
+ 'Testing message sent via SMTP' \
+ 'This is a test that messages are sent via SMTP' \
+ '(message-goto-to)
+ (kill-whole-line)
+ (insert "To: user@example.com\n")'
+sed \
+ -e s',^User-Agent: Notmuch/.* Emacs/.*,User-Agent: Notmuch/XXX Emacs/XXX,' \
+ -e s',^Message-ID: <.*>$,Message-ID: <XXX>,' \
+ -e s',^\(Content-Type: text/plain\); charset=us-ascii$,\1,' < sent_message >OUTPUT
+cat <<EOF >EXPECTED
+From: Notmuch Test Suite <test_suite@notmuchmail.org>
+To: user@example.com
+Subject: Testing message sent via SMTP
+Date: 01 Jan 2000 12:00:00 -0000
+User-Agent: Notmuch/XXX Emacs/XXX
+Message-ID: <XXX>
+MIME-Version: 1.0
+Content-Type: text/plain
+
+This is a test that messages are sent via SMTP
+EOF
+test_expect_equal_file OUTPUT EXPECTED
+
+test_begin_subtest "Verify that sent messages are saved/searchable (via FCC)"
+notmuch new > /dev/null
+output=$(notmuch search 'subject:"testing message sent via SMTP"' | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; Testing message sent via SMTP (inbox)"
+
+test_begin_subtest "notmuch-fcc-dirs set to nil"
+test_emacs "(let ((notmuch-fcc-dirs nil))
+ (notmuch-mua-mail)
+ (test-output))"
+cat <<EOF >EXPECTED
+From: Notmuch Test Suite <test_suite@notmuchmail.org>
+To:
+Subject:
+--text follows this line--
+EOF
+test_expect_equal_file OUTPUT EXPECTED
+
+# Make another FCC maildir specific for the next test
+mkdir -p mail/sent-string/cur
+mkdir -p mail/sent-string/new
+mkdir -p mail/sent-string/tmp
+
+test_begin_subtest "notmuch-fcc-dirs set to a string"
+test_emacs "(let ((notmuch-fcc-dirs \"sent-string\"))
+ (notmuch-mua-mail)
+ (test-output))"
+cat <<EOF >EXPECTED
+From: Notmuch Test Suite <test_suite@notmuchmail.org>
+To:
+Subject:
+Fcc: ${MAIL_DIR}/sent-string
+--text follows this line--
+EOF
+test_expect_equal_file OUTPUT EXPECTED
+
+# Make more FCC maildirs specific for the next test
+mkdir -p mail/sent-list-match/cur
+mkdir -p mail/sent-list-match/new
+mkdir -p mail/sent-list-match/tmp
+mkdir -p mail/failure/cur
+mkdir -p mail/failure/new
+mkdir -p mail/failure/tmp
+
+test_begin_subtest "notmuch-fcc-dirs set to a list (with match)"
+test_emacs "(let ((notmuch-fcc-dirs
+ '((\"notmuchmail.org\" . \"sent-list-match\")
+ (\".*\" . \"failure\"))))
+ (notmuch-mua-mail)
+ (test-output))"
+cat <<EOF >EXPECTED
+From: Notmuch Test Suite <test_suite@notmuchmail.org>
+To:
+Subject:
+Fcc: ${MAIL_DIR}/sent-list-match
+--text follows this line--
+EOF
+test_expect_equal_file OUTPUT EXPECTED
+
+# Make another FCC maildir specific for the next test
+mkdir -p mail/sent-list-catch-all/cur
+mkdir -p mail/sent-list-catch-all/new
+mkdir -p mail/sent-list-catch-all/tmp
+
+test_begin_subtest "notmuch-fcc-dirs set to a list (catch-all)"
+test_emacs "(let ((notmuch-fcc-dirs
+ '((\"example.com\" . \"failure\")
+ (\".*\" . \"sent-list-catch-all\"))))
+ (notmuch-mua-mail)
+ (test-output))"
+cat <<EOF >EXPECTED
+From: Notmuch Test Suite <test_suite@notmuchmail.org>
+To:
+Subject:
+Fcc: ${MAIL_DIR}/sent-list-catch-all
+--text follows this line--
+EOF
+test_expect_equal_file OUTPUT EXPECTED
+
+test_begin_subtest "notmuch-fcc-dirs set to a list (no match)"
+test_emacs "(let ((notmuch-fcc-dirs
+ '((\"example.com\" . \"failure\")
+ (\"nomatchhere.net\" . \"failure\"))))
+ (notmuch-mua-mail)
+ (test-output))"
+cat <<EOF >EXPECTED
+From: Notmuch Test Suite <test_suite@notmuchmail.org>
+To:
+Subject:
+--text follows this line--
+EOF
+test_expect_equal_file OUTPUT EXPECTED
+
+test_begin_subtest "Reply within emacs"
+test_emacs '(let ((message-hidden-headers ''()))
+ (notmuch-search "subject:\"testing message sent via SMTP\"")
+ (notmuch-test-wait)
+ (notmuch-search-reply-to-thread)
+ (test-output))'
+sed -i -e 's/^In-Reply-To: <.*>$/In-Reply-To: <XXX>/' OUTPUT
+sed -i -e 's/^References: <.*>$/References: <XXX>/' OUTPUT
+sed -i -e 's,^User-Agent: Notmuch/.* Emacs/.*,User-Agent: Notmuch/XXX Emacs/XXX,' OUTPUT
+cat <<EOF >EXPECTED
+From: Notmuch Test Suite <test_suite@notmuchmail.org>
+To: user@example.com
+Subject: Re: Testing message sent via SMTP
+In-Reply-To: <XXX>
+Fcc: ${MAIL_DIR}/sent
+References: <XXX>
+User-Agent: Notmuch/XXX Emacs/XXX
+--text follows this line--
+Notmuch Test Suite <test_suite@notmuchmail.org> writes:
+
+> This is a test that messages are sent via SMTP
+EOF
+test_expect_equal_file OUTPUT EXPECTED
+
+test_begin_subtest "Reply from alternate address within emacs"
+add_message '[from]="Sender <sender@example.com>"' \
+ [to]=test_suite_other@notmuchmail.org
+
+test_emacs "(let ((message-hidden-headers '()))
+ (notmuch-search \"id:\\\"${gen_msg_id}\\\"\")
+ (notmuch-test-wait)
+ (notmuch-search-reply-to-thread)
+ (test-output))"
+sed -i -e 's,^User-Agent: Notmuch/.* Emacs/.*,User-Agent: Notmuch/XXX Emacs/XXX,' OUTPUT
+cat <<EOF >EXPECTED
+From: Notmuch Test Suite <test_suite_other@notmuchmail.org>
+To: Sender <sender@example.com>
+Subject: Re: ${test_subtest_name}
+In-Reply-To: <${gen_msg_id}>
+Fcc: ${MAIL_DIR}/sent
+References: <${gen_msg_id}>
+User-Agent: Notmuch/XXX Emacs/XXX
+--text follows this line--
+Sender <sender@example.com> writes:
+
+> This is just a test message (#${gen_msg_cnt})
+EOF
+test_expect_equal_file OUTPUT EXPECTED
+
+test_begin_subtest "Reply from address in named group list within emacs"
+add_message '[from]="Sender <sender@example.com>"' \
+ '[to]=group:test_suite@notmuchmail.org,someone@example.com\;' \
+ [cc]=test_suite_other@notmuchmail.org
+
+test_emacs "(let ((message-hidden-headers '()))
+ (notmuch-search \"id:\\\"${gen_msg_id}\\\"\")
+ (notmuch-test-wait)
+ (notmuch-search-reply-to-thread)
+ (test-output))"
+sed -i -e 's,^User-Agent: Notmuch/.* Emacs/.*,User-Agent: Notmuch/XXX Emacs/XXX,' OUTPUT
+cat <<EOF >EXPECTED
+From: Notmuch Test Suite <test_suite@notmuchmail.org>
+To: Sender <sender@example.com>, someone@example.com
+Subject: Re: ${test_subtest_name}
+In-Reply-To: <${gen_msg_id}>
+Fcc: ${MAIL_DIR}/sent
+References: <${gen_msg_id}>
+User-Agent: Notmuch/XXX Emacs/XXX
+--text follows this line--
+Sender <sender@example.com> writes:
+
+> This is just a test message (#${gen_msg_cnt})
+EOF
+test_expect_equal_file OUTPUT EXPECTED
+
+test_begin_subtest "Reply within emacs to a multipart/mixed message"
+test_emacs '(let ((message-hidden-headers ''()))
+ (notmuch-show "id:20091118002059.067214ed@hikari")
+ (notmuch-show-reply)
+ (test-output))'
+sed -i -e 's,^User-Agent: Notmuch/.* Emacs/.*,User-Agent: Notmuch/XXX Emacs/XXX,' OUTPUT
+cat <<EOF >EXPECTED
+From: Notmuch Test Suite <test_suite@notmuchmail.org>
+To: Adrian Perez de Castro <aperez@igalia.com>, notmuch@notmuchmail.org
+Subject: Re: [notmuch] Introducing myself
+In-Reply-To: <20091118002059.067214ed@hikari>
+Fcc: ${MAIL_DIR}/sent
+References: <20091118002059.067214ed@hikari>
+User-Agent: Notmuch/XXX Emacs/XXX
+--text follows this line--
+Adrian Perez de Castro <aperez@igalia.com> writes:
+
+> Hello to all,
+>
+> I have just heard about Not Much today in some random Linux-related news
+> site (LWN?), my name is Adrian Perez and I work as systems administrator
+> (although I can do some code as well :P). I have always thought that the
+> ideas behind Sup were great, but after some time using it, I got tired of
+> the oddities that it has. I also do not like doing things like having to
+> install Ruby just for reading and sorting mails. Some time ago I thought
+> about doing something like Not Much and in fact I played a bit with the
+> Python+Xapian and the Python+Whoosh combinations, because I find relaxing
+> to code things in Python when I am not working and also it is installed
+> by default on most distribution. I got to have some mailboxes indexed and
+> basic searching working a couple of months ago. Lately I have been very
+> busy and had no time for coding, and them... boom! Not Much appears -- and
+> it is almost exactly what I was trying to do, but faster. I have been
+> playing a bit with Not Much today, and I think it has potential.
+>
+> Also, I would like to share one idea I had in mind, that you might find
+> interesting: One thing I have found very annoying is having to re-tag my
+> mail when the indexes get b0rked (it happened a couple of times to me while
+> using Sup), so I was planning to mails as read/unread and adding the tags
+> not just to the index, but to the mail text itself, e.g. by adding a
+> "X-Tags" header field or by reusing the "Keywords" one. This way, the index
+> could be totally recreated by re-reading the mail directories, and this
+> would also allow to a tools like OfflineIMAP [1] to get the mails into a
+> local maildir, tagging and indexing the mails with the e-mail reader and
+> then syncing back the messages with the "X-Tags" header to the IMAP server.
+> This would allow to use the mail reader from a different computer and still
+> have everything tagged finely.
+>
+> Best regards,
+>
+>
+> ---
+> [1] http://software.complete.org/software/projects/show/offlineimap
+>
+> --
+> Adrian Perez de Castro <aperez@igalia.com>
+> Igalia - Free Software Engineering
+> _______________________________________________
+> notmuch mailing list
+> notmuch@notmuchmail.org
+> http://notmuchmail.org/mailman/listinfo/notmuch
+EOF
+test_expect_equal_file OUTPUT EXPECTED
+
+test_begin_subtest "Reply within emacs to a multipart/alternative message"
+test_emacs '(let ((message-hidden-headers ''()))
+ (notmuch-show "id:cf0c4d610911171136h1713aa59w9cf9aa31f052ad0a@mail.gmail.com")
+ (notmuch-show-reply)
+ (test-output))'
+sed -i -e 's,^User-Agent: Notmuch/.* Emacs/.*,User-Agent: Notmuch/XXX Emacs/XXX,' OUTPUT
+cat <<EOF >EXPECTED
+From: Notmuch Test Suite <test_suite@notmuchmail.org>
+To: Alex Botero-Lowry <alex.boterolowry@gmail.com>, notmuch@notmuchmail.org
+Subject: Re: [notmuch] preliminary FreeBSD support
+In-Reply-To: <cf0c4d610911171136h1713aa59w9cf9aa31f052ad0a@mail.gmail.com>
+Fcc: ${MAIL_DIR}/sent
+References: <cf0c4d610911171136h1713aa59w9cf9aa31f052ad0a@mail.gmail.com>
+User-Agent: Notmuch/XXX Emacs/XXX
+--text follows this line--
+Alex Botero-Lowry <alex.boterolowry@gmail.com> writes:
+
+> I saw the announcement this morning, and was very excited, as I had been
+> hoping sup would be turned into a library,
+> since I like the concept more than the UI (I'd rather an emacs interface).
+>
+> I did a preliminary compile which worked out fine, but
+> sysconf(_SC_SC_GETPW_R_SIZE_MAX) returns -1 on
+> FreeBSD, so notmuch_config_open segfaulted.
+>
+> Attached is a patch that supplies a default buffer size of 64 in cases where
+> -1 is returned.
+>
+> http://www.opengroup.org/austin/docs/austin_328.txt - seems to indicate this
+> is acceptable behavior,
+> and http://mail-index.netbsd.org/pkgsrc-bugs/2006/06/07/msg016808.htmlspecifically
+> uses 64 as the
+> buffer size.
+> _______________________________________________
+> notmuch mailing list
+> notmuch@notmuchmail.org
+> http://notmuchmail.org/mailman/listinfo/notmuch
+EOF
+test_expect_equal_file OUTPUT EXPECTED
+
+test_begin_subtest "Reply within emacs to an html-only message"
+add_message '[content-type]="text/html"' \
+ '[body]="Hi,<br />This is an <b>HTML</b> test message.<br /><br />OK?"'
+test_emacs "(let ((message-hidden-headers '()) (mm-text-html-renderer 'html2text))
+ (notmuch-show \"id:${gen_msg_id}\")
+ (notmuch-show-reply)
+ (test-output))"
+sed -i -e 's,^User-Agent: Notmuch/.* Emacs/.*,User-Agent: Notmuch/XXX Emacs/XXX,' OUTPUT
+cat <<EOF >EXPECTED
+From: Notmuch Test Suite <test_suite@notmuchmail.org>
+To:
+Subject: Re: Reply within emacs to an html-only message
+In-Reply-To: <${gen_msg_id}>
+Fcc: ${MAIL_DIR}/sent
+References: <${gen_msg_id}>
+User-Agent: Notmuch/XXX Emacs/XXX
+--text follows this line--
+Notmuch Test Suite <test_suite@notmuchmail.org> writes:
+
+> Hi,This is an HTML test message.OK?
+EOF
+test_expect_equal_file OUTPUT EXPECTED
+
+test_begin_subtest "Quote MML tags in reply"
+message_id='test-emacs-mml-quoting@message.id'
+add_message [id]="$message_id" \
+ "[subject]='$test_subtest_name'" \
+ '[body]="<#part disposition=inline>"'
+test_emacs "(let ((message-hidden-headers '()))
+ (notmuch-show \"id:$message_id\")
+ (notmuch-show-reply)
+ (test-output))"
+sed -i -e 's,^User-Agent: Notmuch/.* Emacs/.*,User-Agent: Notmuch/XXX Emacs/XXX,' OUTPUT
+cat <<EOF >EXPECTED
+From: Notmuch Test Suite <test_suite@notmuchmail.org>
+To:
+Subject: Re: Quote MML tags in reply
+In-Reply-To: <test-emacs-mml-quoting@message.id>
+Fcc: ${MAIL_DIR}/sent
+References: <test-emacs-mml-quoting@message.id>
+User-Agent: Notmuch/XXX Emacs/XXX
+--text follows this line--
+Notmuch Test Suite <test_suite@notmuchmail.org> writes:
+
+> <#!part disposition=inline>
+EOF
+test_expect_equal_file OUTPUT EXPECTED
+
+test_begin_subtest "Save attachment from within emacs using notmuch-show-save-attachments"
+# save as archive to test that Emacs does not re-compress .gz
+test_emacs '(let ((standard-input "\"attachment1.gz\""))
+ (notmuch-show "id:cf0c4d610911171136h1713aa59w9cf9aa31f052ad0a@mail.gmail.com")
+ (notmuch-show-save-attachments))'
+test_expect_equal_file attachment1.gz "$EXPECTED/attachment"
+
+test_begin_subtest "Save attachment from within emacs using notmuch-show-save-part"
+# save as archive to test that Emacs does not re-compress .gz
+test_emacs '(let ((standard-input "\"attachment2.gz\""))
+ (notmuch-show "id:cf0c4d610911171136h1713aa59w9cf9aa31f052ad0a@mail.gmail.com")
+ (search-forward "0001-Deal-with")
+ (notmuch-show-save-part))'
+test_expect_equal_file attachment2.gz "$EXPECTED/attachment"
+
+test_begin_subtest "Save 8bit attachment from within emacs using notmuch-show-save-attachments"
+
+add_message '[subject]="Attachment with 8bit chars"' \
+ '[header]="MIME-Version: 1.0"' \
+ '[content-type]="multipart/mixed; boundary=\"abcd\""' \
+ '[body]="--abcd
+Content-Type: text/plain
+
+Attachment follows:
+
+--abcd
+Content-Type: application/octet-stream; name=\"sample\"
+Content-Transfer-Encoding: 8bit
+Content-Disposition: attachment; filename=\"sample\"
+
+“¡ Hey ! It compiles ¡ Ship it !”
+
+--abcd--
+"'
+test_emacs '(notmuch-show "id:'"${gen_msg_id}"'")
+ (delete-file "OUTPUT")
+ (let ((standard-input "\"OUTPUT\""))
+ (notmuch-show-save-attachments))'
+
+test_expect_equal "$(cat OUTPUT)" '“¡ Hey ! It compiles ¡ Ship it !”'
+
+test_begin_subtest "View raw message within emacs"
+test_emacs '(notmuch-show "id:cf0c4d610911171136h1713aa59w9cf9aa31f052ad0a@mail.gmail.com")
+ (notmuch-show-view-raw-message)
+ (test-output)'
+test_expect_equal_file OUTPUT $EXPECTED/raw-message-cf0c4d-52ad0a
+
+test_begin_subtest "Hiding/showing signature in notmuch-show view"
+maildir_storage_thread=$(notmuch search --output=threads id:20091117190054.GU3165@dottiness.seas.harvard.edu)
+test_emacs "(notmuch-show \"$maildir_storage_thread\")
+ (search-forward \"Click/Enter to show.\")
+ (button-activate (button-at (point)))
+ (search-backward \"Click/Enter to hide.\")
+ (button-activate (button-at (point)))
+ (test-output)"
+test_expect_equal_file OUTPUT $EXPECTED/notmuch-show-thread-maildir-storage
+
+test_begin_subtest "Detection and hiding of top-post quoting of message"
+add_message '[subject]="The problem with top-posting"' \
+ [id]=top-post-target \
+ '[body]="A: Because it messes up the order in which people normally read text.
+Q: Why is top-posting such a bad thing?
+A: Top-posting.
+Q: What is the most annoying thing in e-mail?"'
+add_message '[from]="Top Poster <top@poster.com>"' \
+ [in-reply-to]=top-post-target \
+ [references]=top-post-target \
+ '[subject]="Re: The problem with top-posting"' \
+ '[body]="Thanks for the advice! I will be sure to put it to good use.
+
+-Top Poster
+
+----- Original Message -----
+From: Notmuch Test Suite <test_suite@notmuchmail.org>
+To: Notmuch Test Suite <test_suite@notmuchmai.org>
+Sent: Fri, 05 Jan 2001 15:43:57 +0000
+Subject: The problem with top-posting
+
+Q: Why is top-posting such a bad thing?
+A: Top-posting.
+Q: What is the most annoying thing in e-mail?"'
+test_emacs "(notmuch-show \"top-posting\")
+ (test-visible-output \"OUTPUT.raw\")"
+echo "Notmuch Test Suite <test_suite@notmuchmail.org> (2001-01-05) (inbox)
+Subject: The problem with top-posting
+To: Notmuch Test Suite <test_suite@notmuchmail.org>
+Date: GENERATED_DATE
+
+A: Because it messes up the order in which people normally read text.
+Q: Why is top-posting such a bad thing?
+A: Top-posting.
+Q: What is the most annoying thing in e-mail?
+Top Poster <top@poster.com> (2001-01-05) (inbox unread)
+Subject: Re: The problem with top-posting
+To: Notmuch Test Suite <test_suite@notmuchmail.org>
+Date: GENERATED_DATE
+
+Thanks for the advice! I will be sure to put it to good use.
+
+-Top Poster
+
+[ 9-line hidden original message. Click/Enter to show. ]" > EXPECTED
+notmuch_date_sanitize < OUTPUT.raw > OUTPUT
+test_expect_equal_file OUTPUT EXPECTED
+
+test_begin_subtest "Hiding message in notmuch-show view"
+test_emacs '(notmuch-show "id:f35dbb950911171438k5df6eb56k77b6c0944e2e79ae@mail.gmail.com")
+ (notmuch-show-toggle-message)
+ (test-visible-output)'
+test_expect_equal_file OUTPUT $EXPECTED/notmuch-show-thread-with-hidden-messages
+
+test_begin_subtest "Hiding message with visible citation in notmuch-show view"
+test_emacs '(notmuch-show "id:f35dbb950911171438k5df6eb56k77b6c0944e2e79ae@mail.gmail.com")
+ (search-forward "Click/Enter to show.")
+ (button-activate (button-at (point)))
+ (notmuch-show-toggle-message)
+ (test-visible-output)'
+test_expect_equal_file OUTPUT $EXPECTED/notmuch-show-thread-with-hidden-messages
+
+test_begin_subtest "notmuch-show: show message headers"
+test_emacs \
+ '(let ((notmuch-message-headers '\''("Subject" "To" "Cc" "Date"))
+ (notmuch-message-headers-visible t))
+ (notmuch-show "id:f35dbb950911171438k5df6eb56k77b6c0944e2e79ae@mail.gmail.com")
+ (test-visible-output))'
+test_expect_equal_file OUTPUT $EXPECTED/notmuch-show-message-with-headers-visible
+
+test_begin_subtest "notmuch-show: hide message headers"
+test_emacs \
+ '(let ((notmuch-message-headers '\''("Subject" "To" "Cc" "Date"))
+ (notmuch-message-headers-visible nil))
+ (notmuch-show "id:f35dbb950911171438k5df6eb56k77b6c0944e2e79ae@mail.gmail.com")
+ (test-visible-output))'
+test_expect_equal_file OUTPUT $EXPECTED/notmuch-show-message-with-headers-hidden
+
+test_begin_subtest "notmuch-show: hide message headers (w/ notmuch-show-toggle-visibility-headers)"
+test_emacs \
+ '(let ((notmuch-message-headers '\''("Subject" "To" "Cc" "Date"))
+ (notmuch-message-headers-visible t))
+ (notmuch-show "id:f35dbb950911171438k5df6eb56k77b6c0944e2e79ae@mail.gmail.com")
+ (notmuch-show-toggle-visibility-headers)
+ (test-visible-output))'
+test_expect_equal_file OUTPUT $EXPECTED/notmuch-show-message-with-headers-hidden
+
+test_begin_subtest "notmuch-show: collapse all messages in thread"
+test_emacs '(notmuch-show "id:f35dbb950911171435ieecd458o853c873e35f4be95@mail.gmail.com")
+ (let ((current-prefix-arg t))
+ (notmuch-show-open-or-close-all)
+ (test-visible-output))'
+test_expect_equal_file OUTPUT $EXPECTED/notmuch-show-thread-with-all-messages-collapsed
+
+test_begin_subtest "notmuch-show: uncollapse all messages in thread"
+test_emacs '(notmuch-show "id:f35dbb950911171435ieecd458o853c873e35f4be95@mail.gmail.com")
+ (notmuch-show-open-or-close-all)
+ (test-visible-output)'
+test_expect_equal_file OUTPUT $EXPECTED/notmuch-show-thread-with-all-messages-uncollapsed
+
+test_begin_subtest "Stashing in notmuch-show"
+add_message '[date]="Sat, 01 Jan 2000 12:00:00 -0000"' \
+ '[from]="Some One <someone@somewhere.org>"' \
+ '[to]="Some One Else <notsomeone@somewhere.org>"' \
+ '[cc]="Notmuch <notmuch@notmuchmail.org>"' \
+ '[subject]="Stash my stashables"' \
+ '[id]="bought"' \
+ '[body]="Unable to stash body. Where did you get it in the first place?!?"'
+notmuch tag +stashtest id:${gen_msg_id}
+test_emacs '(notmuch-show "id:\"bought\"")
+ (notmuch-show-stash-date)
+ (notmuch-show-stash-from)
+ (notmuch-show-stash-to)
+ (notmuch-show-stash-cc)
+ (notmuch-show-stash-subject)
+ (notmuch-show-stash-message-id)
+ (notmuch-show-stash-message-id-stripped)
+ (notmuch-show-stash-tags)
+ (notmuch-show-stash-filename)
+ (notmuch-show-stash-mlarchive-link "Gmane")
+ (notmuch-show-stash-mlarchive-link "MARC")
+ (notmuch-show-stash-mlarchive-link "Mail Archive, The")
+ (switch-to-buffer
+ (generate-new-buffer "*test-stashing*"))
+ (dotimes (i 12)
+ (yank)
+ (insert "\n")
+ (rotate-yank-pointer 1))
+ (reverse-region (point-min) (point-max))
+ (test-output)'
+cat <<EOF >EXPECTED
+Sat, 01 Jan 2000 12:00:00 +0000
+Some One <someone@somewhere.org>
+Some One Else <notsomeone@somewhere.org>
+Notmuch <notmuch@notmuchmail.org>
+Stash my stashables
+id:bought
+bought
+inbox,stashtest
+${gen_msg_filename}
+http://mid.gmane.org/bought
+http://marc.info/?i=bought
+http://mid.mail-archive.com/bought
+EOF
+test_expect_equal_file OUTPUT EXPECTED
+
+test_begin_subtest "Stashing in notmuch-search"
+test_emacs '(notmuch-search "id:\"bought\"")
+ (notmuch-test-wait)
+ (notmuch-search-stash-thread-id)
+ (switch-to-buffer
+ (generate-new-buffer "*test-stashing*"))
+ (yank)
+ (test-output)'
+sed -i -e 's/^thread:.*$/thread:XXX/' OUTPUT
+test_expect_equal "$(cat OUTPUT)" "thread:XXX"
+
+test_begin_subtest 'notmuch-show-advance-and-archive with invisible signature'
+message1='id:20091118010116.GC25380@dottiness.seas.harvard.edu'
+message2='id:1258491078-29658-1-git-send-email-dottedmag@dottedmag.net'
+test_emacs "(notmuch-show \"$message2\")
+ (test-output \"EXPECTED\")"
+test_emacs "(notmuch-search \"$message1 or $message2\")
+ (notmuch-test-wait)
+ (notmuch-search-show-thread)
+ (goto-char (point-max))
+ (redisplay)
+ (notmuch-show-advance-and-archive)
+ (test-output)"
+test_expect_equal_file OUTPUT EXPECTED
+
+test_begin_subtest "Refresh show buffer"
+test_emacs '(notmuch-show "id:f35dbb950911171438k5df6eb56k77b6c0944e2e79ae@mail.gmail.com")
+ (test-visible-output "EXPECTED")
+ (notmuch-show-refresh-view)
+ (test-visible-output)'
+test_expect_equal_file OUTPUT EXPECTED
+
+test_begin_subtest "Refresh modified show buffer"
+test_emacs '(notmuch-show "id:f35dbb950911171438k5df6eb56k77b6c0944e2e79ae@mail.gmail.com")
+ (notmuch-show-toggle-message)
+ (notmuch-show-next-message)
+ (notmuch-show-toggle-message)
+ (test-visible-output "EXPECTED")
+ (notmuch-show-refresh-view)
+ (test-visible-output)'
+test_expect_equal_file OUTPUT EXPECTED
+
+test_begin_subtest "Do not call notmuch for non-inlinable application/mpeg parts"
+id='message-with-application/mpeg-attachment@notmuchmail.org'
+emacs_fcc_message \
+ 'Message with application/mpeg attachment' \
+ '' \
+ "(message-goto-eoh)
+ (insert \"Message-ID: <$id>\n\")
+ (message-goto-body)
+ (mml-insert-part \"application/mpeg\")
+ (insert \"a fake mp3 file\")"
+notmuch_counter_reset
+test_emacs "(let ((notmuch-command \"$notmuch_counter_command\"))
+ (notmuch-show \"id:$id\"))"
+test_expect_equal $(notmuch_counter_value) 1
+
+test_begin_subtest "Do not call notmuch for non-inlinable audio/mpeg parts"
+id='message-with-audio/mpeg-attachment@notmuchmail.org'
+emacs_fcc_message \
+ 'Message with audio/mpeg attachment' \
+ '' \
+ "(message-goto-eoh)
+ (insert \"Message-ID: <$id>\n\")
+ (message-goto-body)
+ (mml-insert-part \"audio/mpeg\")
+ (insert \"a fake mp3 file\")"
+notmuch_counter_reset
+test_emacs "(let ((notmuch-command \"$notmuch_counter_command\"))
+ (notmuch-show \"id:$id\"))"
+test_expect_equal $(notmuch_counter_value) 1
+
+test_begin_subtest "notmuch-hello-mode hook is called"
+counter=$(test_emacs \
+ '(let ((notmuch-hello-mode-hook-counter 0))
+ (kill-buffer "*notmuch-hello*")
+ (notmuch-hello)
+ notmuch-hello-mode-hook-counter)'
+)
+test_expect_equal "$counter" 1
+
+test_begin_subtest "notmuch-hello-mode hook is not called on updates"
+counter=$(test_emacs \
+ '(let ((notmuch-hello-mode-hook-counter 0))
+ (kill-buffer "*notmuch-hello*")
+ (notmuch-hello)
+ (notmuch-hello-update)
+ notmuch-hello-mode-hook-counter)'
+)
+test_expect_equal "$counter" 1
+
+test_begin_subtest "notmuch-hello-refresh hook is called"
+counter=$(test_emacs \
+ '(let ((notmuch-hello-refresh-hook-counter 0))
+ (kill-buffer "*notmuch-hello*")
+ (notmuch-hello)
+ notmuch-hello-refresh-hook-counter)'
+)
+test_expect_equal "$counter" 1
+
+test_begin_subtest "notmuch-hello-refresh hook is called on updates"
+counter=$(test_emacs \
+ '(let ((notmuch-hello-refresh-hook-counter 0))
+ (kill-buffer "*notmuch-hello*")
+ (notmuch-hello)
+ (notmuch-hello-update)
+ notmuch-hello-refresh-hook-counter)'
+)
+test_expect_equal "$counter" 2
+
+
+add_message '[subject]="HTML mail with images"' \
+ '[content-type]="multipart/related; boundary=abcd"' \
+ '[body]="--abcd
+Content-Type: text/html
+
+<img src="cid:330@goomoji.gmail"> smiley
+
+--abcd
+Content-Type: image/gif
+Content-Transfer-Encoding: base64
+Content-ID: <330@goomoji.gmail>
+
+R0lGODlhDAAMAKIFAF5LAP/zxAAAANyuAP/gaP///wAAAAAAACH5BAEAAAUALAAAAAAMAAwAAAMl
+WLPcGjDKFYi9lxKBOaGcF35DhWHamZUW0K4mAbiwWtuf0uxFAgA7
+--abcd--"'
+test_emacs "(let ((mm-text-html-renderer
+ (if (assq 'shr mm-text-html-renderer-alist)
+ 'shr 'html2text)))
+ (notmuch-show \"id:${gen_msg_id}\"))
+ (test-output)" > /dev/null
+# Different Emacs versions and renderers give very different results,
+# so just check that something reasonable showed up. We first cat the
+# output so the test framework will print it if the test fails.
+test_expect_success "Rendering HTML mail with images" \
+ 'cat OUTPUT && grep -q smiley OUTPUT'
+
+
+test_begin_subtest "Search handles subprocess error exit codes"
+cat > notmuch_fail <<EOF
+#!/bin/sh
+echo '()'
+exit 1
+EOF
+chmod a+x notmuch_fail
+test_emacs "(let ((notmuch-command \"$PWD/notmuch_fail\"))
+ (with-current-buffer \"*Messages*\" (erase-buffer))
+ (with-current-buffer (get-buffer-create \"*Notmuch errors*\")
+ (erase-buffer))
+ (notmuch-search \"tag:inbox\")
+ (notmuch-test-wait)
+ (with-current-buffer \"*Messages*\"
+ (test-output \"MESSAGES\"))
+ (with-current-buffer \"*Notmuch errors*\"
+ (test-output \"ERROR\"))
+ (test-output))"
+
+test_expect_equal "$(notmuch_emacs_error_sanitize notmuch_fail OUTPUT MESSAGES ERROR)" "\
+=== OUTPUT ===
+End of search results.
+=== MESSAGES ===
+YYY/notmuch_fail exited with status 1 (see *Notmuch errors* for more details)
+=== ERROR ===
+[XXX]
+YYY/notmuch_fail exited with status 1
+command: YYY/notmuch_fail search --format\=sexp --format-version\=2 --sort\=newest-first tag\:inbox
+exit status: 1"
+
+test_begin_subtest "Search handles subprocess warnings"
+cat > notmuch_fail <<EOF
+#!/bin/sh
+echo '()'
+echo This is a warning >&2
+echo This is another warning >&2
+exit 0
+EOF
+chmod a+x notmuch_fail
+test_emacs "(let ((notmuch-command \"$PWD/notmuch_fail\"))
+ (with-current-buffer \"*Messages*\" (erase-buffer))
+ (with-current-buffer (get-buffer-create \"*Notmuch errors*\")
+ (erase-buffer))
+ (notmuch-search \"tag:inbox\")
+ (notmuch-test-wait)
+ (with-current-buffer \"*Messages*\"
+ (test-output \"MESSAGES\"))
+ (with-current-buffer \"*Notmuch errors*\"
+ (test-output \"ERROR\"))
+ (test-output))"
+sed -i -e 's/^\[.*\]$/[XXX]/' ERROR
+test_expect_equal "$(cat OUTPUT; echo ---; cat MESSAGES; echo ---; cat ERROR)" "\
+End of search results.
+---
+This is a warning (see *Notmuch errors* for more details)
+---
+[XXX]
+This is a warning
+This is another warning"
+
+test_begin_subtest "Search thread tag operations are race-free"
+add_message '[subject]="Search race test"'
+gen_msg_id_1=$gen_msg_id
+generate_message '[in-reply-to]="<'$gen_msg_id_1'>"' \
+ '[references]="<'$gen_msg_id_1'>"' \
+ '[subject]="Search race test two"'
+test_emacs '(notmuch-search "subject:\"search race test\"")
+ (notmuch-test-wait)
+ (notmuch-poll)
+ (execute-kbd-macro "+search-thread-race-tag")'
+output=$(notmuch search --output=messages 'tag:search-thread-race-tag')
+test_expect_equal "$output" "id:$gen_msg_id_1"
+
+test_begin_subtest "Search global tag operations are race-free"
+generate_message '[in-reply-to]="<'$gen_msg_id_1'>"' \
+ '[references]="<'$gen_msg_id_1'>"' \
+ '[subject]="Re: Search race test"'
+test_emacs '(notmuch-search "subject:\"search race test\" -subject:two")
+ (notmuch-test-wait)
+ (notmuch-poll)
+ (execute-kbd-macro "*+search-global-race-tag")'
+output=$(notmuch search --output=messages 'tag:search-global-race-tag')
+test_expect_equal "$output" "id:$gen_msg_id_1"
+
+test_done
--- /dev/null
+#!/usr/bin/env bash
+test_description="Emacs with large search results buffer"
+. ./test-lib.sh
+
+x=xxxxxxxxxx # 10
+x=$x$x$x$x$x$x$x$x$x$x # 100
+x=$x$x$x$x$x$x$x$x$x # 900
+
+# We generate a long subject here (over 900 bytes) so that the emacs
+# search results get large quickly. With 30 such messages we should
+# cross several 4kB page boundaries and see the bug.
+n=30
+for i in $(seq 1 $n); do
+ # Roughly 100B2 KiB per message. That is, we need two messages in order to
+ # exceed the typical size of the pipe buffer (4 KiB on commodity systems).
+ generate_message '[subject]="$x $i of $n"'
+done
+
+notmuch new > /dev/null
+
+test_begin_subtest "Ensure that emacs doesn't drop results"
+notmuch search '*' > EXPECTED
+sed -i -e 's/^thread:[0-9a-f]* //' -e 's/;//' -e 's/xx*/[BLOB]/' EXPECTED
+echo 'End of search results.' >> EXPECTED
+
+test_emacs '(notmuch-search "*")
+ (notmuch-test-wait)
+ (test-output)'
+sed -i -e s', *, ,g' -e 's/xxx*/[BLOB]/g' OUTPUT
+test_expect_equal_file OUTPUT EXPECTED
+
+test_done
--- /dev/null
+#!/usr/bin/env bash
+
+test_description="emacs: mail subject to filename"
+. ./test-lib.sh
+
+# emacs server can't be started in a child process with $(test_emacs ...)
+test_emacs '(ignore)' > /dev/null
+
+# test notmuch-wash-subject-to-patch-sequence-number (subject)
+test_begin_subtest "no patch sequence number"
+output=$(test_emacs '(format "%S" (notmuch-wash-subject-to-patch-sequence-number
+ "[PATCH] A normal patch subject without numbers"))'
+)
+test_expect_equal "$output" '"nil"'
+
+test_begin_subtest "patch sequence number #1"
+output=$(test_emacs '(notmuch-wash-subject-to-patch-sequence-number
+ "[PATCH 2/3] A most regular patch subject")'
+)
+test_expect_equal "$output" 2
+
+test_begin_subtest "patch sequence number #2"
+output=$(test_emacs '(notmuch-wash-subject-to-patch-sequence-number
+ " [dummy list prefix] [RFC PATCH v2 13/42] Special prefixes")'
+)
+test_expect_equal "$output" 13
+
+test_begin_subtest "patch sequence number #3"
+output=$(test_emacs '(notmuch-wash-subject-to-patch-sequence-number
+ "[PATCH 2/3] [PATCH 032/037] use the last prefix")'
+)
+test_expect_equal "$output" 32
+
+test_begin_subtest "patch sequence number #4"
+output=$(test_emacs '(notmuch-wash-subject-to-patch-sequence-number
+ "[dummy list prefix] [PATCH 2/3] PATCH 3/3] do not use a broken prefix")'
+)
+test_expect_equal "$output" 2
+
+test_begin_subtest "patch sequence number #5"
+output=$(test_emacs '(notmuch-wash-subject-to-patch-sequence-number
+ "[RFC][PATCH 3/5][PATCH 4/5][PATCH 5/5] A made up test")'
+)
+test_expect_equal "$output" 5
+
+test_begin_subtest "patch sequence number #6"
+output=$(test_emacs '(notmuch-wash-subject-to-patch-sequence-number
+ "[PATCH 2/3] this -> [PATCH 3/3] is not a prefix anymore [nor this 4/4]")'
+)
+test_expect_equal "$output" 2
+
+test_begin_subtest "patch sequence number #7"
+output=$(test_emacs '(notmuch-wash-subject-to-patch-sequence-number
+ "[liberally accept crapola right before123/456and after] the numbers")'
+)
+test_expect_equal "$output" 123
+
+# test notmuch-wash-subject-to-filename (subject &optional maxlen)
+test_begin_subtest "filename #1"
+output=$(test_emacs '(notmuch-wash-subject-to-filename
+ "just a subject line")'
+)
+test_expect_equal "$output" '"just-a-subject-line"'
+
+test_begin_subtest "filename #2"
+output=$(test_emacs '(notmuch-wash-subject-to-filename
+ " [any] [prefixes are ] [removed!] from the subject")'
+)
+test_expect_equal "$output" '"from-the-subject"'
+
+test_begin_subtest "filename #3"
+output=$(test_emacs '(notmuch-wash-subject-to-filename
+ " leading and trailing space ")'
+)
+test_expect_equal "$output" '"leading-and-trailing-space"'
+
+test_begin_subtest "filename #4"
+output=$(test_emacs '(notmuch-wash-subject-to-filename
+ "!# leading ()// &%, and in between_and_trailing garbage ()(&%%")'
+)
+test_expect_equal "$output" '"-leading-and-in-between_and_trailing-garbage"'
+
+test_begin_subtest "filename #5"
+output=$(test_emacs '(notmuch-wash-subject-to-filename
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.-_01234567890")'
+)
+test_expect_equal "$output" '"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.-_01234567890"'
+
+test_begin_subtest "filename #6"
+output=$(test_emacs '(notmuch-wash-subject-to-filename
+ "sequences of ... are squashed and trailing are removed ...")'
+)
+test_expect_equal "$output" '"sequences-of-.-are-squashed-and-trailing-are-removed"'
+
+test_begin_subtest "filename #7"
+output=$(test_emacs '(notmuch-wash-subject-to-filename
+ "max length test" 1)'
+)
+test_expect_equal "$output" '"m"'
+
+test_begin_subtest "filename #8"
+output=$(test_emacs '(notmuch-wash-subject-to-filename
+ "max length test /&(/%&/%%&¤%¤" 20)'
+)
+test_expect_equal "$output" '"max-length-test"'
+
+test_begin_subtest "filename #9"
+output=$(test_emacs '(notmuch-wash-subject-to-filename
+ "[a prefix] [is only separated] by [spaces], so \"by\" is not okay!")'
+)
+test_expect_equal "$output" '"by-spaces-so-by-is-not-okay"'
+
+# test notmuch-wash-subject-to-patch-filename (subject)
+test_begin_subtest "patch filename #1"
+output=$(test_emacs '(notmuch-wash-subject-to-patch-filename
+ "[RFC][PATCH 099/100] rewrite notmuch")'
+)
+test_expect_equal "$output" '"0099-rewrite-notmuch.patch"'
+
+test_begin_subtest "patch filename #2"
+output=$(test_emacs '(notmuch-wash-subject-to-patch-filename
+ "[RFC PATCH v1] has no patch number, default to 1")'
+)
+test_expect_equal "$output" '"0001-has-no-patch-number-default-to-1.patch"'
+
+test_begin_subtest "patch filename #3"
+output=$(test_emacs '(notmuch-wash-subject-to-patch-filename
+ "[PATCH 4/5] the maximum length of a patch filename is 52 + patch sequence number + .patch extension")'
+)
+test_expect_equal "$output" '"0004-the-maximum-length-of-a-patch-filename-is-52-patch-s.patch"'
+
+test_begin_subtest "patch filename #4"
+output=$(test_emacs '(notmuch-wash-subject-to-patch-filename
+ "[PATCH 4/5] the maximum length of a patch filename is 52 + patchh ! sequence number + .patch extension, *before* trimming trailing - and .")'
+)
+test_expect_equal "$output" '"0004-the-maximum-length-of-a-patch-filename-is-52-patchh.patch"'
+
+test_done
--- /dev/null
+#!/usr/bin/env bash
+
+test_description="maildir synchronization"
+
+. ./test-lib.sh
+
+# Create the expected maildir structure
+mkdir $MAIL_DIR/cur
+mkdir $MAIL_DIR/new
+mkdir $MAIL_DIR/tmp
+
+test_begin_subtest "Adding 'S' flag to existing filename removes 'unread' tag"
+add_message [subject]='"Adding S flag"' [filename]='adding-s-flag:2,' [dir]=cur
+output=$(notmuch search subject:"Adding S flag" | notmuch_search_sanitize)
+output+="
+"
+mv "${gen_msg_filename}" "${gen_msg_filename}S"
+output+=$(NOTMUCH_NEW)
+output+="
+"
+output+=$(notmuch search subject:"Adding S flag" | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Adding S flag (inbox unread)
+No new mail. Detected 1 file rename.
+thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Adding S flag (inbox)"
+
+test_begin_subtest "Adding message with 'S' flag prevents 'unread' tag"
+add_message [subject]='"Adding message with S"' [filename]='adding-with-s-flag:2,S' [dir]=cur
+output=$(notmuch search subject:"Adding message with S" | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Adding message with S (inbox)"
+
+test_begin_subtest "Adding 'replied' tag adds 'R' flag to filename"
+add_message [subject]='"Adding replied tag"' [filename]='adding-replied-tag:2,S' [dir]=cur
+notmuch tag +replied subject:"Adding replied tag"
+output=$(cd ${MAIL_DIR}/cur; ls -1 adding-replied*)
+test_expect_equal "$output" "adding-replied-tag:2,RS"
+
+test_begin_subtest "notmuch show works with renamed file (without notmuch new)"
+output=$(notmuch show --format=json id:${gen_msg_id} | notmuch_json_show_sanitize)
+test_expect_equal_json "$output" '[[[{"id": "XXXXX",
+"match": true,
+"excluded": false,
+"filename": "YYYYY",
+"timestamp": 42,
+"date_relative": "2001-01-05",
+"tags": ["inbox","replied"],
+"headers": {"Subject": "Adding replied tag",
+"From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
+"To": "Notmuch Test Suite <test_suite@notmuchmail.org>",
+"Date": "GENERATED_DATE"},
+"body": [{"id": 1,
+"content-type": "text/plain",
+"content": "This is just a test message (#3)\n"}]},
+[]]]]'
+
+test_expect_success 'notmuch reply works with renamed file (without notmuch new)' 'notmuch reply id:${gen_msg_id}'
+
+test_begin_subtest "notmuch new detects no file rename after tag->flag synchronization"
+output=$(NOTMUCH_NEW)
+test_expect_equal "$output" "No new mail."
+
+test_begin_subtest "When read, message moved from new to cur"
+add_message [subject]='"Message to move to cur"' [date]='"Sat, 01 Jan 2000 12:00:00 -0000"' [filename]='message-to-move-to-cur' [dir]=new
+notmuch tag -unread subject:"Message to move to cur"
+output=$(cd "$MAIL_DIR/cur"; ls message-to-move*)
+test_expect_equal "$output" "message-to-move-to-cur:2,S"
+
+test_begin_subtest "No rename should be detected by notmuch new"
+output=$(NOTMUCH_NEW)
+test_expect_equal "$output" "No new mail."
+# (*) If notmuch new was not run we've got "Processed 1 file in almost
+# no time" here. The reason is that removing unread tag in a previous
+# test created directory document in the database but this document
+# was not linked as subdirectory of $MAIL_DIR. Therefore notmuch new
+# could not reach the cur/ directory and its files in it during
+# recursive traversal.
+#
+# XXX: The above sounds like a bug that should be fixed. If notmuch is
+# creating new directories in the mail store, then it should be
+# creating all necessary database state for those directories.
+
+test_begin_subtest "Adding non-maildir tags does not move message from new to cur"
+add_message [subject]='"Message to stay in new"' \
+ [date]='"Sat, 01 Jan 2000 12:00:00 -0000"' \
+ [filename]='message-to-stay-in-new' [dir]=new
+notmuch tag +donotmove subject:"Message to stay in new"
+output=$(cd "$MAIL_DIR"; ls */message-to-stay-in-new*)
+test_expect_equal "$output" "new/message-to-stay-in-new"
+
+test_begin_subtest "Message in cur lacking maildir info gets one on any tag change"
+add_message [filename]='message-to-get-maildir-info' [dir]=cur
+notmuch tag +anytag id:$gen_msg_id
+output=$(cd "$MAIL_DIR"; ls */message-to-get-maildir-info*)
+test_expect_equal "$output" "cur/message-to-get-maildir-info:2,"
+
+test_begin_subtest "Message in new with maildir info is moved to cur on any tag change"
+add_message [filename]='message-with-info-to-be-moved-to-cur:2,' [dir]=new
+notmuch tag +anytag id:$gen_msg_id
+output=$(cd "$MAIL_DIR"; ls */message-with-info-to-be-moved-to-cur*)
+test_expect_equal "$output" "cur/message-with-info-to-be-moved-to-cur:2,"
+
+test_begin_subtest "Removing 'S' flag from existing filename adds 'unread' tag"
+add_message [subject]='"Removing S flag"' [filename]='removing-s-flag:2,S' [dir]=cur
+output=$(notmuch search subject:"Removing S flag" | notmuch_search_sanitize)
+output+="
+"
+mv "${gen_msg_filename}" "${gen_msg_filename%S}"
+output+=$(NOTMUCH_NEW)
+output+="
+"
+output+=$(notmuch search subject:"Removing S flag" | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Removing S flag (inbox)
+No new mail. Detected 1 file rename.
+thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Removing S flag (inbox unread)"
+
+test_begin_subtest "Removing info from filename leaves tags unchanged"
+add_message [subject]='"Message to lose maildir info"' [filename]='message-to-lose-maildir-info' [dir]=cur
+notmuch tag -unread subject:"Message to lose maildir info"
+mv "$MAIL_DIR/cur/message-to-lose-maildir-info:2,S" "$MAIL_DIR/cur/message-without-maildir-info"
+output=$(NOTMUCH_NEW)
+output+="
+"
+output+=$(notmuch search subject:"Message to lose maildir info" | notmuch_search_sanitize)
+test_expect_equal "$output" "No new mail. Detected 1 file rename.
+thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Message to lose maildir info (inbox)"
+
+add_message [subject]='"Non-maildir message"' [dir]=notmaildir [filename]='non-maildir-message'
+expected=$(notmuch search --output=files subject:"Non-maildir message")
+test_expect_success "Can remove unread tag from message in non-maildir directory" 'notmuch tag -unread subject:"Non-maildir message"'
+
+test_begin_subtest "Message in non-maildir directory does not get renamed"
+output=$(notmuch search --output=files subject:"Non-maildir message")
+test_expect_equal "$output" "$expected"
+
+test_begin_subtest "notmuch dump/restore re-synchronizes maildir tags with flags"
+# Capture current filename state
+expected=$(ls $MAIL_DIR/cur)
+# Add/remove some flags from filenames
+mv $MAIL_DIR/cur/adding-replied-tag:2,RS $MAIL_DIR/cur/adding-replied-tag:2,S
+mv $MAIL_DIR/cur/adding-s-flag:2,S $MAIL_DIR/cur/adding-s-flag:2,
+mv $MAIL_DIR/cur/adding-with-s-flag:2,S $MAIL_DIR/cur/adding-with-s-flag:2,RS
+mv $MAIL_DIR/cur/message-to-move-to-cur:2,S $MAIL_DIR/cur/message-to-move-to-cur:2,DS
+notmuch dump --output=dump.txt
+NOTMUCH_NEW >/dev/null
+notmuch restore --input=dump.txt
+output=$(ls $MAIL_DIR/cur)
+test_expect_equal "$output" "$expected"
+
+test_begin_subtest 'Adding flags to duplicate message tags the mail'
+add_message [subject]='"Duplicated message"' [dir]=cur [filename]='duplicated-message:2,'
+cp "$MAIL_DIR/cur/duplicated-message:2," "$MAIL_DIR/cur/duplicated-message-copy:2,RS"
+NOTMUCH_NEW > output
+notmuch search subject:"Duplicated message" | notmuch_search_sanitize >> output
+test_expect_equal "$(< output)" "No new mail.
+thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Duplicated message (inbox replied)"
+
+test_begin_subtest "Adding duplicate message without flags does not remove tags"
+cp "$MAIL_DIR/cur/duplicated-message-copy:2,RS" "$MAIL_DIR/cur/duplicated-message-another-copy:2,"
+NOTMUCH_NEW > output
+notmuch search subject:"Duplicated message" | notmuch_search_sanitize >> output
+test_expect_equal "$(< output)" "No new mail.
+thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Duplicated message (inbox replied)"
+
+test_begin_subtest "Tag changes modify flags of multiple files"
+notmuch tag -replied subject:"Duplicated message"
+(cd $MAIL_DIR/cur/; ls duplicated*) > actual
+test_expect_equal "$(< actual)" "duplicated-message-another-copy:2,S
+duplicated-message-copy:2,S
+duplicated-message:2,S"
+
+test_begin_subtest "Synchronizing tag changes preserves unsupported maildir flags"
+add_message [subject]='"Unsupported maildir flags"' [dir]=cur [filename]='unsupported-maildir-flags:2,FSZxyz'
+notmuch tag +unread +draft -flagged subject:"Unsupported maildir flags"
+test_expect_equal "$(cd $MAIL_DIR/cur/; ls unsupported*)" "unsupported-maildir-flags:2,DZxyz"
+
+test_begin_subtest "A file with non-compliant maildir info will not be renamed"
+add_message [subject]='"Non-compliant maildir info"' [dir]=cur [filename]='non-compliant-maildir-info:2,These-are-not-flags-in-ASCII-order-donottouch'
+notmuch tag +unread +draft -flagged subject:"Non-compliant maildir info"
+test_expect_equal "$(cd $MAIL_DIR/cur/; ls non-compliant*)" "non-compliant-maildir-info:2,These-are-not-flags-in-ASCII-order-donottouch"
+
+test_begin_subtest "Files in new/ get default synchronized tags"
+OLDCONFIG=$(notmuch config get new.tags)
+notmuch config set new.tags test
+add_message [subject]='"File in new/"' [dir]=new [filename]='file-in-new'
+notmuch config set new.tags $OLDCONFIG
+notmuch search 'subject:"File in new"' | notmuch_search_sanitize > output
+test_expect_equal "$(< output)" \
+"thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; File in new/ (test unread)"
+
+test_done
--- /dev/null
+#!/usr/bin/env bash
+
+# TODO:
+# - decryption/verification with signer key not available
+# - verification of signatures from expired/revoked keys
+
+test_description='PGP/MIME signature verification and decryption'
+. ./test-lib.sh
+
+add_gnupg_home ()
+{
+ local output
+ [ -d ${GNUPGHOME} ] && return
+ mkdir -m 0700 "$GNUPGHOME"
+ gpg --no-tty --import <$TEST_DIRECTORY/gnupg-secret-key.asc >"$GNUPGHOME"/import.log 2>&1
+ test_debug "cat $GNUPGHOME/import.log"
+ if (gpg --quick-random --version >/dev/null 2>&1) ; then
+ echo quick-random >> "$GNUPGHOME"/gpg.conf
+ elif (gpg --debug-quick-random --version >/dev/null 2>&1) ; then
+ echo debug-quick-random >> "$GNUPGHOME"/gpg.conf
+ fi
+ echo no-emit-version >> "$GNUPGHOME"/gpg.conf
+}
+
+##################################################
+
+add_gnupg_home
+# get key fingerprint
+FINGERPRINT=$(gpg --no-tty --list-secret-keys --with-colons --fingerprint | grep '^fpr:' | cut -d: -f10)
+
+test_expect_success 'emacs delivery of signed message' \
+'emacs_fcc_message \
+ "test signed message 001" \
+ "This is a test signed message." \
+ "(mml-secure-message-sign)"'
+
+test_begin_subtest "signature verification"
+output=$(notmuch show --format=json --verify subject:"test signed message 001" \
+ | notmuch_json_show_sanitize \
+ | sed -e 's|"created": [1234567890]*|"created": 946728000|')
+expected='[[[{"id": "XXXXX",
+ "match": true,
+ "excluded": false,
+ "filename": "YYYYY",
+ "timestamp": 946728000,
+ "date_relative": "2000-01-01",
+ "tags": ["inbox","signed"],
+ "headers": {"Subject": "test signed message 001",
+ "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
+ "To": "test_suite@notmuchmail.org",
+ "Date": "Sat, 01 Jan 2000 12:00:00 +0000"},
+ "body": [{"id": 1,
+ "sigstatus": [{"status": "good",
+ "fingerprint": "'$FINGERPRINT'",
+ "created": 946728000}],
+ "content-type": "multipart/signed",
+ "content": [{"id": 2,
+ "content-type": "text/plain",
+ "content": "This is a test signed message.\n"},
+ {"id": 3,
+ "content-type": "application/pgp-signature",
+ "content-length": 280}]}]},
+ []]]]'
+test_expect_equal_json \
+ "$output" \
+ "$expected"
+
+test_begin_subtest "signature verification with full owner trust"
+# give the key full owner trust
+echo "${FINGERPRINT}:6:" | gpg --no-tty --import-ownertrust >>"$GNUPGHOME"/trust.log 2>&1
+gpg --no-tty --check-trustdb >>"$GNUPGHOME"/trust.log 2>&1
+output=$(notmuch show --format=json --verify subject:"test signed message 001" \
+ | notmuch_json_show_sanitize \
+ | sed -e 's|"created": [1234567890]*|"created": 946728000|')
+expected='[[[{"id": "XXXXX",
+ "match": true,
+ "excluded": false,
+ "filename": "YYYYY",
+ "timestamp": 946728000,
+ "date_relative": "2000-01-01",
+ "tags": ["inbox","signed"],
+ "headers": {"Subject": "test signed message 001",
+ "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
+ "To": "test_suite@notmuchmail.org",
+ "Date": "Sat, 01 Jan 2000 12:00:00 +0000"},
+ "body": [{"id": 1,
+ "sigstatus": [{"status": "good",
+ "fingerprint": "'$FINGERPRINT'",
+ "created": 946728000,
+ "userid": " Notmuch Test Suite <test_suite@notmuchmail.org> (INSECURE!)"}],
+ "content-type": "multipart/signed",
+ "content": [{"id": 2,
+ "content-type": "text/plain",
+ "content": "This is a test signed message.\n"},
+ {"id": 3,
+ "content-type": "application/pgp-signature",
+ "content-length": 280}]}]},
+ []]]]'
+test_expect_equal_json \
+ "$output" \
+ "$expected"
+
+test_begin_subtest "signature verification with signer key unavailable"
+# move the gnupghome temporarily out of the way
+mv "${GNUPGHOME}"{,.bak}
+output=$(notmuch show --format=json --verify subject:"test signed message 001" \
+ | notmuch_json_show_sanitize \
+ | sed -e 's|"created": [1234567890]*|"created": 946728000|')
+expected='[[[{"id": "XXXXX",
+ "match": true,
+ "excluded": false,
+ "filename": "YYYYY",
+ "timestamp": 946728000,
+ "date_relative": "2000-01-01",
+ "tags": ["inbox","signed"],
+ "headers": {"Subject": "test signed message 001",
+ "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
+ "To": "test_suite@notmuchmail.org",
+ "Date": "Sat, 01 Jan 2000 12:00:00 +0000"},
+ "body": [{"id": 1,
+ "sigstatus": [{"status": "error",
+ "keyid": "'$(echo $FINGERPRINT | cut -c 25-)'",
+ "errors": 2}],
+ "content-type": "multipart/signed",
+ "content": [{"id": 2,
+ "content-type": "text/plain",
+ "content": "This is a test signed message.\n"},
+ {"id": 3,
+ "content-type": "application/pgp-signature",
+ "content-length": 280}]}]},
+ []]]]'
+test_expect_equal_json \
+ "$output" \
+ "$expected"
+mv "${GNUPGHOME}"{.bak,}
+
+# create a test encrypted message with attachment
+cat <<EOF >TESTATTACHMENT
+This is a test file.
+EOF
+test_expect_success 'emacs delivery of encrypted message with attachment' \
+'emacs_fcc_message \
+ "test encrypted message 001" \
+ "This is a test encrypted message.\n" \
+ "(mml-attach-file \"TESTATTACHMENT\") (mml-secure-message-encrypt)"'
+
+test_begin_subtest "decryption, --format=text"
+output=$(notmuch show --format=text --decrypt subject:"test encrypted message 001" \
+ | notmuch_show_sanitize_all \
+ | sed -e 's|"created": [1234567890]*|"created": 946728000|')
+expected='\fmessage{ id:XXXXX depth:0 match:1 excluded:0 filename:XXXXX
+\fheader{
+Notmuch Test Suite <test_suite@notmuchmail.org> (2000-01-01) (encrypted inbox)
+Subject: test encrypted message 001
+From: Notmuch Test Suite <test_suite@notmuchmail.org>
+To: test_suite@notmuchmail.org
+Date: Sat, 01 Jan 2000 12:00:00 +0000
+\fheader}
+\fbody{
+\fpart{ ID: 1, Content-type: multipart/encrypted
+\fpart{ ID: 2, Content-type: application/pgp-encrypted
+Non-text part: application/pgp-encrypted
+\fpart}
+\fpart{ ID: 3, Content-type: multipart/mixed
+\fpart{ ID: 4, Content-type: text/plain
+This is a test encrypted message.
+\fpart}
+\fattachment{ ID: 5, Filename: TESTATTACHMENT, Content-type: application/octet-stream
+Non-text part: application/octet-stream
+\fattachment}
+\fpart}
+\fpart}
+\fbody}
+\fmessage}'
+test_expect_equal \
+ "$output" \
+ "$expected"
+
+test_begin_subtest "decryption, --format=json"
+output=$(notmuch show --format=json --decrypt subject:"test encrypted message 001" \
+ | notmuch_json_show_sanitize \
+ | sed -e 's|"created": [1234567890]*|"created": 946728000|')
+expected='[[[{"id": "XXXXX",
+ "match": true,
+ "excluded": false,
+ "filename": "YYYYY",
+ "timestamp": 946728000,
+ "date_relative": "2000-01-01",
+ "tags": ["encrypted","inbox"],
+ "headers": {"Subject": "test encrypted message 001",
+ "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
+ "To": "test_suite@notmuchmail.org",
+ "Date": "Sat, 01 Jan 2000 12:00:00 +0000"},
+ "body": [{"id": 1,
+ "encstatus": [{"status": "good"}],
+ "sigstatus": [],
+ "content-type": "multipart/encrypted",
+ "content": [{"id": 2,
+ "content-type": "application/pgp-encrypted",
+ "content-length": 11},
+ {"id": 3,
+ "content-type": "multipart/mixed",
+ "content": [{"id": 4,
+ "content-type": "text/plain",
+ "content": "This is a test encrypted message.\n"},
+ {"id": 5,
+ "content-type": "application/octet-stream",
+ "content-length": 28,
+ "content-transfer-encoding": "base64",
+ "filename": "TESTATTACHMENT"}]}]}]},
+ []]]]'
+test_expect_equal_json \
+ "$output" \
+ "$expected"
+
+test_begin_subtest "decryption, --format=json, --part=4"
+output=$(notmuch show --format=json --part=4 --decrypt subject:"test encrypted message 001" \
+ | notmuch_json_show_sanitize \
+ | sed -e 's|"created": [1234567890]*|"created": 946728000|')
+expected='{"id": 4,
+ "content-type": "text/plain",
+ "content": "This is a test encrypted message.\n"}'
+test_expect_equal_json \
+ "$output" \
+ "$expected"
+
+test_begin_subtest "decrypt attachment (--part=5 --format=raw)"
+notmuch show \
+ --format=raw \
+ --part=5 \
+ --decrypt \
+ subject:"test encrypted message 001" >OUTPUT
+test_expect_equal_file OUTPUT TESTATTACHMENT
+
+test_begin_subtest "decryption failure with missing key"
+mv "${GNUPGHOME}"{,.bak}
+# The length of the encrypted attachment varies so must be normalized.
+output=$(notmuch show --format=json --decrypt subject:"test encrypted message 001" \
+ | notmuch_json_show_sanitize \
+ | sed -e 's|"created": [1234567890]*|"created": 946728000|' \
+ | sed -e 's|"content-length": 6[1234567890]*|"content-length": 652|')
+expected='[[[{"id": "XXXXX",
+ "match": true,
+ "excluded": false,
+ "filename": "YYYYY",
+ "timestamp": 946728000,
+ "date_relative": "2000-01-01",
+ "tags": ["encrypted","inbox"],
+ "headers": {"Subject": "test encrypted message 001",
+ "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
+ "To": "test_suite@notmuchmail.org",
+ "Date": "Sat, 01 Jan 2000 12:00:00 +0000"},
+ "body": [{"id": 1,
+ "encstatus": [{"status": "bad"}],
+ "content-type": "multipart/encrypted",
+ "content": [{"id": 2,
+ "content-type": "application/pgp-encrypted",
+ "content-length": 11},
+ {"id": 3,
+ "content-type": "application/octet-stream",
+ "content-length": 652}]}]},
+ []]]]'
+test_expect_equal_json \
+ "$output" \
+ "$expected"
+mv "${GNUPGHOME}"{.bak,}
+
+test_expect_success 'emacs delivery of encrypted + signed message' \
+'emacs_fcc_message \
+ "test encrypted message 002" \
+ "This is another test encrypted message.\n" \
+ "(mml-secure-message-sign-encrypt)"'
+
+test_begin_subtest "decryption + signature verification"
+output=$(notmuch show --format=json --decrypt subject:"test encrypted message 002" \
+ | notmuch_json_show_sanitize \
+ | sed -e 's|"created": [1234567890]*|"created": 946728000|')
+expected='[[[{"id": "XXXXX",
+ "match": true,
+ "excluded": false,
+ "filename": "YYYYY",
+ "timestamp": 946728000,
+ "date_relative": "2000-01-01",
+ "tags": ["encrypted","inbox"],
+ "headers": {"Subject": "test encrypted message 002",
+ "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
+ "To": "test_suite@notmuchmail.org",
+ "Date": "Sat, 01 Jan 2000 12:00:00 +0000"},
+ "body": [{"id": 1,
+ "encstatus": [{"status": "good"}],
+ "sigstatus": [{"status": "good",
+ "fingerprint": "'$FINGERPRINT'",
+ "created": 946728000,
+ "userid": " Notmuch Test Suite <test_suite@notmuchmail.org> (INSECURE!)"}],
+ "content-type": "multipart/encrypted",
+ "content": [{"id": 2,
+ "content-type": "application/pgp-encrypted",
+ "content-length": 11},
+ {"id": 3,
+ "content-type": "text/plain",
+ "content": "This is another test encrypted message.\n"}]}]},
+ []]]]'
+test_expect_equal_json \
+ "$output" \
+ "$expected"
+
+test_begin_subtest "reply to encrypted message"
+output=$(notmuch reply --decrypt subject:"test encrypted message 002" \
+ | grep -v -e '^In-Reply-To:' -e '^References:')
+expected='From: Notmuch Test Suite <test_suite@notmuchmail.org>
+Subject: Re: test encrypted message 002
+
+On 01 Jan 2000 12:00:00 -0000, Notmuch Test Suite <test_suite@notmuchmail.org> wrote:
+> This is another test encrypted message.'
+test_expect_equal \
+ "$output" \
+ "$expected"
+
+test_begin_subtest "signature verification with revoked key"
+# generate revocation certificate and load it to revoke key
+echo "y
+1
+Notmuch Test Suite key revocation (automated) $(date '+%F_%T%z')
+
+y
+
+" \
+ | gpg --no-tty --quiet --command-fd 0 --armor --gen-revoke "0x${FINGERPRINT}!" 2>/dev/null \
+ | gpg --no-tty --quiet --import
+output=$(notmuch show --format=json --verify subject:"test signed message 001" \
+ | notmuch_json_show_sanitize \
+ | sed -e 's|"created": [1234567890]*|"created": 946728000|')
+expected='[[[{"id": "XXXXX",
+ "match": true,
+ "excluded": false,
+ "filename": "YYYYY",
+ "timestamp": 946728000,
+ "date_relative": "2000-01-01",
+ "tags": ["inbox","signed"],
+ "headers": {"Subject": "test signed message 001",
+ "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
+ "To": "test_suite@notmuchmail.org",
+ "Date": "Sat, 01 Jan 2000 12:00:00 +0000"},
+ "body": [{"id": 1,
+ "sigstatus": [{"status": "error",
+ "keyid": "6D92612D94E46381",
+ "errors": 8}],
+ "content-type": "multipart/signed",
+ "content": [{"id": 2,
+ "content-type": "text/plain",
+ "content": "This is a test signed message.\n"},
+ {"id": 3,
+ "content-type": "application/pgp-signature",
+ "content-length": 280}]}]},
+ []]]]'
+test_expect_equal_json \
+ "$output" \
+ "$expected"
+
+test_done
--- /dev/null
+#!/usr/bin/env bash
+#
+# Copyright (c) 2011 David Bremner
+#
+
+# This test tests whether hiding Xapian::Error symbols in libnotmuch
+# also hides them for other users of libxapian. This is motivated by
+# the discussion in http://gcc.gnu.org/wiki/Visibility'
+
+test_description='exception symbol hiding'
+
+. ./test-lib.sh
+
+run_test(){
+ result=$(LD_LIBRARY_PATH="$TEST_DIRECTORY/../lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" $TEST_DIRECTORY/symbol-test 2>&1)
+}
+
+output="A Xapian exception occurred opening database: Couldn't stat 'fakedb/.notmuch/xapian'
+caught No chert database found at path \`./nonexistant'"
+
+mkdir -p fakedb/.notmuch
+
+test_expect_success 'running test' run_test
+
+test_begin_subtest 'checking output'
+test_expect_equal "$result" "$output"
+
+test_begin_subtest 'comparing existing to exported symbols'
+objdump -t $TEST_DIRECTORY/../lib/*.o | awk '$4 == ".text" && $6 ~ "^notmuch" {print $6}' | sort | uniq > ACTUAL
+sed -n 's/[[:blank:]]*\(notmuch_[^;]*\);/\1/p' $TEST_DIRECTORY/../notmuch.sym | sort | uniq > EXPORTED
+test_expect_equal_file EXPORTED ACTUAL
+
+test_done
--- /dev/null
+#!/usr/bin/env bash
+test_description='folder tags removed and added through file renames remain consistent'
+. ./test-lib.sh
+
+test_begin_subtest "No new messages"
+output=$(NOTMUCH_NEW)
+test_expect_equal "$output" "No new mail."
+
+
+test_begin_subtest "Single new message"
+generate_message
+file_x=$gen_msg_filename
+id_x=$gen_msg_id
+output=$(NOTMUCH_NEW)
+test_expect_equal "$output" "Added 1 new message to the database."
+
+test_begin_subtest "Add second folder for same message"
+dir=$(dirname $file_x)
+mkdir $dir/spam
+cp $file_x $dir/spam
+output=$(NOTMUCH_NEW)
+test_expect_equal "$output" "No new mail."
+
+
+test_begin_subtest "Multiple files for same message"
+cat <<EOF >EXPECTED
+MAIL_DIR/msg-001
+MAIL_DIR/spam/msg-001
+EOF
+notmuch search --output=files id:$id_x | sed -e "s,$MAIL_DIR,MAIL_DIR," >OUTPUT
+test_expect_equal_file OUTPUT EXPECTED
+
+test_begin_subtest "Test matches folder:spam"
+output=$(notmuch search folder:spam)
+test_expect_equal "$output" "thread:0000000000000001 2001-01-05 [1/1] Notmuch Test Suite; Single new message (inbox unread)"
+
+test_begin_subtest "Remove folder:spam copy of email"
+rm $dir/spam/$(basename $file_x)
+output=$(NOTMUCH_NEW)
+test_expect_equal "$output" "No new mail. Detected 1 file rename."
+
+test_begin_subtest "No mails match the folder:spam search"
+output=$(notmuch search folder:spam)
+test_expect_equal "$output" ""
+
+test_done
--- /dev/null
+#!/usr/bin/env bash
+test_description='atomicity'
+. ./test-lib.sh
+
+# This script tests the effects of killing and restarting "notmuch
+# new" at arbitrary points. If notmuch new is properly atomic, the
+# final database contents should be the same regardless of when (or
+# if) it is killed and restarted.
+
+if test_require_external_prereq gdb; then
+
+# Create a maildir structure to also stress flag synchronization
+ mkdir $MAIL_DIR/cur
+ mkdir $MAIL_DIR/new
+ mkdir $MAIL_DIR/tmp
+ mkdir $MAIL_DIR/.remove-dir
+
+ # Prepare the initial database
+ generate_message [subject]='Duplicate' [filename]='duplicate:2,' [dir]=cur
+ generate_message [subject]='Remove' [filename]='remove:2,' [dir]=cur
+ generate_message [subject]='"Remove duplicate"' [filename]='remove-duplicate:2,' [dir]=cur
+ cp $MAIL_DIR/cur/remove-duplicate:2, $MAIL_DIR/cur/remove-duplicate-copy:2,
+ generate_message [subject]='Rename' [filename]='rename:2,' [dir]=cur
+ generate_message [subject]='"Rename duplicate"' [filename]='rename-duplicate:2,' [dir]=cur
+ generate_message [subject]='"Move 1"' [filename]='move1:2,' [dir]=cur
+ generate_message [subject]='"Move 2"' [filename]='move2:2,' [dir]=new
+ generate_message [subject]='Flag' [filename]='flag:2,' [dir]=cur
+ generate_message [subject]='"Flag duplicate"' [filename]='flag-duplicate:2,' [dir]=cur
+ cp $MAIL_DIR/cur/flag-duplicate:2, $MAIL_DIR/cur/flag-duplicate-copy:2,F
+ generate_message [subject]='"Remove directory"' [filename]='remove-directory:2,' [dir]=.remove-dir
+ generate_message [subject]='"Remove directory duplicate"' [filename]='remove-directory-duplicate:2,' [dir]=.remove-dir
+ cp $MAIL_DIR/.remove-dir/remove-directory-duplicate:2, $MAIL_DIR/cur/
+ notmuch new > /dev/null
+
+ # Make all maildir changes, but *don't* update the database
+ generate_message [subject]='Added' [filename]='added:2,' [dir]=cur
+ cp $MAIL_DIR/cur/duplicate:2, $MAIL_DIR/cur/duplicate-copy:2,
+ generate_message [subject]='"Add duplicate"' [filename]='add-duplicate:2,' [dir]=cur
+ generate_message [subject]='"Add duplicate copy"' [filename]='add-duplicate-copy:2,' [dir]=cur
+ rm $MAIL_DIR/cur/remove:2,
+ rm $MAIL_DIR/cur/remove-duplicate-copy:2,
+ mv $MAIL_DIR/cur/rename:2, $MAIL_DIR/cur/renamed:2,
+ mv $MAIL_DIR/cur/rename-duplicate:2, $MAIL_DIR/cur/renamed-duplicate:2,
+ mv $MAIL_DIR/cur/move1:2, $MAIL_DIR/new/move1:2,
+ mv $MAIL_DIR/new/move2:2, $MAIL_DIR/cur/move2:2,
+ mv $MAIL_DIR/cur/flag:2, $MAIL_DIR/cur/flag:2,F
+ rm $MAIL_DIR/cur/flag-duplicate-copy:2,F
+ rm $MAIL_DIR/.remove-dir/remove-directory:2,
+ rm $MAIL_DIR/.remove-dir/remove-directory-duplicate:2,
+ rmdir $MAIL_DIR/.remove-dir
+
+ # Prepare a snapshot of the updated maildir. The gdb script will
+ # update the database in this snapshot as it goes.
+ cp -a $MAIL_DIR $MAIL_DIR.snap
+ cp ${NOTMUCH_CONFIG} ${NOTMUCH_CONFIG}.snap
+ NOTMUCH_CONFIG=${NOTMUCH_CONFIG}.snap notmuch config set database.path $MAIL_DIR.snap
+
+
+
+ # Execute notmuch new and, at every call to rename, snapshot the
+ # database, run notmuch new again on the snapshot, and capture the
+ # results of search.
+ #
+ # -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 >/dev/null 2>/dev/null
+
+ # Get the final, golden output
+ notmuch search '*' > expected
+
+ # Check output against golden output
+ outcount=$(cat outcount)
+ echo -n > searchall
+ echo -n > expectall
+ for ((i = 0; i < $outcount; i++)); do
+ if ! cmp -s search.$i expected; then
+ # Find the range of interruptions that match this output
+ for ((end = $i + 1 ; end < $outcount; end++)); do
+ if ! cmp -s search.$i search.$end; then
+ break
+ fi
+ done
+ echo "When interrupted after $test/backtrace.$(expr $i - 1) (abort points $i-$(expr $end - 1))" >> searchall
+ cat search.$i >> searchall
+ cat expected >> expectall
+ echo >> searchall
+ echo >> expectall
+
+ i=$(expr $end - 1)
+ fi
+ done
+fi
+
+test_begin_subtest '"notmuch new" is idempotent under arbitrary aborts'
+test_expect_equal_file searchall expectall
+
+test_expect_success "detected $outcount>10 abort points" "test $outcount -gt 10"
+
+test_done
--- /dev/null
+#!/usr/bin/env bash
+test_description="python bindings"
+. ./test-lib.sh
+
+add_email_corpus
+
+test_begin_subtest "compare thread ids"
+test_python <<EOF
+import notmuch
+db = notmuch.Database(mode=notmuch.Database.MODE.READ_ONLY)
+q_new = notmuch.Query(db, 'tag:inbox')
+q_new.set_sort(notmuch.Query.SORT.OLDEST_FIRST)
+for t in q_new.search_threads():
+ print t.get_thread_id()
+EOF
+notmuch search --sort=oldest-first --output=threads tag:inbox | sed s/^thread:// > EXPECTED
+test_expect_equal_file OUTPUT EXPECTED
+
+test_begin_subtest "compare message ids"
+test_python <<EOF
+import notmuch
+db = notmuch.Database(mode=notmuch.Database.MODE.READ_ONLY)
+q_new = notmuch.Query(db, 'tag:inbox')
+q_new.set_sort(notmuch.Query.SORT.OLDEST_FIRST)
+for m in q_new.search_messages():
+ print m.get_message_id()
+EOF
+notmuch search --sort=oldest-first --output=messages tag:inbox | sed s/^id:// > EXPECTED
+test_expect_equal_file OUTPUT EXPECTED
+
+test_begin_subtest "get non-existent file"
+test_python <<EOF
+import notmuch
+db = notmuch.Database(mode=notmuch.Database.MODE.READ_ONLY)
+print db.find_message_by_filename("i-dont-exist")
+EOF
+test_expect_equal "$(cat OUTPUT)" "None"
+
+test_done
--- /dev/null
+#!/usr/bin/env bash
+test_description='hooks'
+. ./test-lib.sh
+
+HOOK_DIR=${MAIL_DIR}/.notmuch/hooks
+
+create_echo_hook () {
+ local TOKEN="${RANDOM}"
+ mkdir -p ${HOOK_DIR}
+ cat <<EOF >"${HOOK_DIR}/${1}"
+#!/bin/sh
+echo "${TOKEN}" > ${3}
+EOF
+ chmod +x "${HOOK_DIR}/${1}"
+ echo "${TOKEN}" > ${2}
+}
+
+create_failing_hook () {
+ mkdir -p ${HOOK_DIR}
+ cat <<EOF >"${HOOK_DIR}/${1}"
+#!/bin/sh
+exit 13
+EOF
+ chmod +x "${HOOK_DIR}/${1}"
+}
+
+rm_hooks () {
+ rm -rf ${HOOK_DIR}
+}
+
+# add a message to generate mail dir and database
+add_message
+
+test_begin_subtest "pre-new is run"
+rm_hooks
+generate_message
+create_echo_hook "pre-new" expected output
+notmuch new > /dev/null
+test_expect_equal_file expected output
+
+test_begin_subtest "post-new is run"
+rm_hooks
+generate_message
+create_echo_hook "post-new" expected output
+notmuch new > /dev/null
+test_expect_equal_file expected output
+
+test_begin_subtest "pre-new is run before post-new"
+rm_hooks
+generate_message
+create_echo_hook "pre-new" pre-new.expected pre-new.output
+create_echo_hook "post-new" post-new.expected post-new.output
+notmuch new > /dev/null
+test_expect_equal_file post-new.expected post-new.output
+
+test_begin_subtest "pre-new non-zero exit status (hook status)"
+rm_hooks
+generate_message
+create_failing_hook "pre-new"
+output=`notmuch new 2>&1`
+test_expect_equal "$output" "Error: pre-new hook failed with status 13"
+
+# depends on the previous subtest leaving broken hook behind
+test_expect_code 1 "pre-new non-zero exit status (notmuch status)" "notmuch new"
+
+# depends on the previous subtests leaving 1 new message behind
+test_begin_subtest "pre-new non-zero exit status aborts new"
+rm_hooks
+output=$(NOTMUCH_NEW)
+test_expect_equal "$output" "Added 1 new message to the database."
+
+test_begin_subtest "post-new non-zero exit status (hook status)"
+rm_hooks
+generate_message
+create_failing_hook "post-new"
+NOTMUCH_NEW 2>output.stderr >output
+cat output.stderr >> output
+echo "Added 1 new message to the database." > expected
+echo "Error: post-new hook failed with status 13" >> expected
+test_expect_equal_file expected output
+
+# depends on the previous subtest leaving broken hook behind
+test_expect_code 1 "post-new non-zero exit status (notmuch status)" "notmuch new"
+
+# test_begin_subtest "hook without executable permissions"
+rm_hooks
+mkdir -p ${HOOK_DIR}
+cat <<EOF >"${HOOK_DIR}/pre-new"
+#!/bin/sh
+echo foo
+EOF
+output=`notmuch new 2>&1`
+test_expect_code 1 "hook without executable permissions" "notmuch new"
+
+# test_begin_subtest "hook execution failure"
+rm_hooks
+mkdir -p ${HOOK_DIR}
+cat <<EOF >"${HOOK_DIR}/pre-new"
+no hashbang, execl fails
+EOF
+chmod +x "${HOOK_DIR}/pre-new"
+test_expect_code 1 "hook execution failure" "notmuch new"
+
+test_done
--- /dev/null
+#!/usr/bin/env bash
+test_description="argument parsing"
+. ./test-lib.sh
+
+test_begin_subtest "sanity check"
+$TEST_DIRECTORY/arg-test pos1 --keyword=one --string=foo pos2 --int=7 > OUTPUT
+cat <<EOF > EXPECTED
+keyword 1
+int 7
+string foo
+positional arg 1 pos1
+positional arg 2 pos2
+EOF
+test_expect_equal_file OUTPUT EXPECTED
+
+test_done
--- /dev/null
+#!/usr/bin/env bash
+
+test_description="emacs test function sanity"
+. ./test-lib.sh
+
+test_begin_subtest "emacs test function sanity"
+test_emacs_expect_t 't'
+
+test_done
--- /dev/null
+#!/usr/bin/env bash
+
+test_description="emacs address cleaning"
+. ./test-lib.sh
+
+test_begin_subtest "notmuch-test-address-clean part 1"
+test_emacs_expect_t '(notmuch-test-address-cleaning-1)'
+
+test_begin_subtest "notmuch-test-address-clean part 2"
+test_emacs_expect_t '(notmuch-test-address-cleaning-2)'
+
+test_begin_subtest "notmuch-test-address-clean part 3"
+test_emacs_expect_t '(notmuch-test-address-cleaning-3)'
+
+test_done
--- /dev/null
+#!/usr/bin/env bash
+
+test_description="emacs notmuch-hello view"
+. ./test-lib.sh
+
+EXPECTED=$TEST_DIRECTORY/emacs.expected-output
+
+add_email_corpus
+
+test_begin_subtest "User-defined section with inbox tag"
+test_emacs "(let ((notmuch-hello-sections
+ (list (lambda () (notmuch-hello-insert-searches
+ \"Test\" '((\"inbox\" . \"tag:inbox\")))))))
+ (notmuch-hello)
+ (test-output))"
+test_expect_equal_file OUTPUT $EXPECTED/notmuch-hello-new-section
+
+test_begin_subtest "User-defined section with empty, hidden entry"
+test_emacs "(let ((notmuch-hello-sections
+ (list (lambda () (notmuch-hello-insert-searches
+ \"Test-with-empty\"
+ '((\"inbox\" . \"tag:inbox\")
+ (\"doesnotexist\" . \"tag:doesnotexist\"))
+ :hide-empty-searches t)))))
+ (notmuch-hello)
+ (test-output))"
+test_expect_equal_file OUTPUT $EXPECTED/notmuch-hello-section-with-empty
+
+test_begin_subtest "User-defined section, unread tag filtered out"
+test_emacs "(let ((notmuch-hello-sections
+ (list (lambda () (notmuch-hello-insert-tags-section
+ \"Test-with-filtered\"
+ :hide-tags '(\"unread\"))))))
+ (notmuch-hello)
+ (test-output))"
+test_expect_equal_file OUTPUT $EXPECTED/notmuch-hello-section-hidden-tag
+
+test_begin_subtest "User-defined section, different query for counts"
+test_emacs "(let ((notmuch-hello-sections
+ (list (lambda () (notmuch-hello-insert-tags-section
+ \"Test-with-counts\"
+ :filter-count \"tag:signed\")))))
+ (notmuch-hello)
+ (test-output))"
+test_expect_equal_file OUTPUT $EXPECTED/notmuch-hello-section-counts
+
+test_begin_subtest "Empty custom tags section"
+test_emacs "(let* ((widget (widget-create 'notmuch-hello-tags-section))
+ (notmuch-hello-sections (list (widget-value widget))))
+ (notmuch-hello)
+ (test-output))"
+test_expect_equal_file OUTPUT $EXPECTED/notmuch-hello-empty-custom-tags-section
+
+test_begin_subtest "Empty custom queries section"
+test_emacs "(let* ((widget (widget-create 'notmuch-hello-query-section))
+ (notmuch-hello-sections (list (widget-value widget))))
+ (notmuch-hello)
+ (test-output))"
+test_expect_equal_file OUTPUT $EXPECTED/notmuch-hello-empty-custom-queries-section
+
+test_begin_subtest "Column alignment for tag/queries with long names"
+tag=a-very-long-tag # length carefully calculated for 80 characters window width
+notmuch tag +$tag '*'
+test_emacs '(notmuch-hello)
+ (test-output)'
+notmuch tag -$tag '*'
+test_expect_equal_file OUTPUT $EXPECTED/notmuch-hello-long-names
+
+test_done
--- /dev/null
+#!/usr/bin/env bash
+
+test_description="emacs notmuch-show view"
+. ./test-lib.sh
+
+EXPECTED=$TEST_DIRECTORY/emacs-show.expected-output
+
+add_email_corpus
+
+test_begin_subtest "Hiding Original Message region at beginning of a message"
+message_id='OriginalMessageHiding.1@notmuchmail.org'
+add_message \
+ [id]="$message_id" \
+ '[subject]="Hiding Original Message region at beginning of a message"' \
+ '[body]="-----Original Message-----
+Text here."'
+
+cat <<EOF >EXPECTED
+Notmuch Test Suite <test_suite@notmuchmail.org> (2001-01-05) (inbox)
+Subject: Hiding Original Message region at beginning of a message
+To: Notmuch Test Suite <test_suite@notmuchmail.org>
+Date: GENERATED_DATE
+
+[ 2-line hidden original message. Click/Enter to show. ]
+EOF
+
+test_emacs "(notmuch-show \"id:$message_id\")
+ (test-visible-output \"OUTPUT.raw\")"
+notmuch_date_sanitize < OUTPUT.raw > OUTPUT
+test_expect_equal_file OUTPUT EXPECTED
+
+test_begin_subtest "Bare subject #1"
+output=$(test_emacs '(notmuch-show-strip-re "Re: subject")')
+test_expect_equal "$output" '"subject"'
+
+test_begin_subtest "Bare subject #2"
+output=$(test_emacs '(notmuch-show-strip-re "re:Re: re: Re: re:subject")')
+test_expect_equal "$output" '"subject"'
+
+test_begin_subtest "Bare subject #3"
+output=$(test_emacs '(notmuch-show-strip-re "the cure: fix the regexp")')
+test_expect_equal "$output" '"the cure: fix the regexp"'
+
+test_begin_subtest "don't process cryptographic MIME parts"
+test_emacs '(let ((notmuch-crypto-process-mime nil))
+ (notmuch-show "id:20091117203301.GV3165@dottiness.seas.harvard.edu")
+ (test-visible-output))'
+test_expect_equal_file OUTPUT $EXPECTED/notmuch-show-process-crypto-mime-parts-off
+
+test_begin_subtest "process cryptographic MIME parts"
+test_emacs '(let ((notmuch-crypto-process-mime t))
+ (notmuch-show "id:20091117203301.GV3165@dottiness.seas.harvard.edu")
+ (test-visible-output))'
+test_expect_equal_file OUTPUT $EXPECTED/notmuch-show-process-crypto-mime-parts-on
+
+test_begin_subtest "process cryptographic MIME parts (w/ notmuch-show-toggle-process-crypto)"
+test_emacs '(let ((notmuch-crypto-process-mime nil))
+ (notmuch-show "id:20091117203301.GV3165@dottiness.seas.harvard.edu")
+ (notmuch-show-toggle-process-crypto)
+ (test-visible-output))'
+test_expect_equal_file OUTPUT $EXPECTED/notmuch-show-process-crypto-mime-parts-on
+
+test_begin_subtest "notmuch-show: don't elide non-matching messages"
+test_emacs '(let ((notmuch-show-only-matching-messages nil))
+ (notmuch-search "from:lars@seas.harvard.edu and subject:\"Maildir storage\"")
+ (notmuch-test-wait)
+ (notmuch-search-show-thread)
+ (notmuch-test-wait)
+ (test-visible-output))'
+test_expect_equal_file OUTPUT $EXPECTED/notmuch-show-elide-non-matching-messages-off
+
+test_begin_subtest "notmuch-show: elide non-matching messages"
+test_emacs '(let ((notmuch-show-only-matching-messages t))
+ (notmuch-search "from:lars@seas.harvard.edu and subject:\"Maildir storage\"")
+ (notmuch-test-wait)
+ (notmuch-search-show-thread)
+ (notmuch-test-wait)
+ (test-visible-output))'
+test_expect_equal_file OUTPUT $EXPECTED/notmuch-show-elide-non-matching-messages-on
+
+test_begin_subtest "notmuch-show: elide non-matching messages (w/ notmuch-show-toggle-elide-non-matching)"
+test_emacs '(let ((notmuch-show-only-matching-messages nil))
+ (notmuch-search "from:lars@seas.harvard.edu and subject:\"Maildir storage\"")
+ (notmuch-test-wait)
+ (notmuch-search-show-thread)
+ (notmuch-test-wait)
+ (notmuch-show-toggle-elide-non-matching)
+ (test-visible-output))'
+test_expect_equal_file OUTPUT $EXPECTED/notmuch-show-elide-non-matching-messages-on
+
+test_begin_subtest "notmuch-show: elide non-matching messages (w/ prefix arg to notmuch-show)"
+test_emacs '(let ((notmuch-show-only-matching-messages nil))
+ (notmuch-search "from:lars@seas.harvard.edu and subject:\"Maildir storage\"")
+ (notmuch-test-wait)
+ (notmuch-search-show-thread t)
+ (notmuch-test-wait)
+ (test-visible-output))'
+test_expect_equal_file OUTPUT $EXPECTED/notmuch-show-elide-non-matching-messages-on
+
+test_begin_subtest "notmuch-show: disable indentation of thread content (w/ notmuch-show-toggle-thread-indentation)"
+test_emacs '(notmuch-search "from:lars@seas.harvard.edu and subject:\"Maildir storage\"")
+ (notmuch-test-wait)
+ (notmuch-search-show-thread)
+ (notmuch-test-wait)
+ (notmuch-show-toggle-thread-indentation)
+ (test-visible-output)'
+test_expect_equal_file OUTPUT $EXPECTED/notmuch-show-indent-thread-content-off
+
+test_begin_subtest "id buttonization"
+add_message '[body]="
+id:abc
+id:abc.def. id:abc,def, id:abc;def; id:abc:def:
+id:foo@bar.?baz? id:foo@bar!.baz!
+(id:foo@bar.baz) [id:foo@bar.baz]
+id:foo@bar.baz...
+id:2+2=5
+id:=_-:/.[]@$%+
+id:abc)def
+id:ab\"c def
+id:\"abc\"def
+id:\"ab\"\"c\"def
+id:\"ab c\"def
+id:\"abc\".def
+id:\"abc
+\"
+id:)
+id:
+cid:xxx
+mid:abc mid:abc/def
+mid:abc%20def
+mid:abc. mid:abc, mid:abc;"'
+test_emacs '(notmuch-show "id:'$gen_msg_id'")
+ (notmuch-test-mark-links)
+ (test-visible-output "OUTPUT.raw")'
+cat <<EOF >EXPECTED
+Notmuch Test Suite <test_suite@notmuchmail.org> (2001-01-05) (inbox)
+Subject: id buttonization
+To: Notmuch Test Suite <test_suite@notmuchmail.org>
+Date: GENERATED_DATE
+
+<<id:abc>>
+<<id:abc.def>>. <<id:abc,def>>, <<id:abc;def>>; <<id:abc:def>>:
+<<id:foo@bar.?baz>>? <<id:foo@bar!.baz>>!
+(<<id:foo@bar.baz>>) [<<id:foo@bar.baz>>]
+<<id:foo@bar.baz>>...
+<<id:2+2=5>>
+<<id:=_-:/.[]@$%+>>
+<<id:abc>>)def
+<<id:ab"c>> def
+<<id:"abc">>def
+<<id:"ab""c">>def
+<<id:"ab c">>def
+<<id:"abc">>.def
+id:"abc
+"
+id:)
+id:
+cid:xxx
+<<mid:abc>> <<mid:abc/def>>
+<<mid:abc%20def>>
+<<mid:abc>>. <<mid:abc>>, <<mid:abc>>;
+EOF
+notmuch_date_sanitize < OUTPUT.raw > OUTPUT
+test_expect_equal_file OUTPUT EXPECTED
+
+
+test_begin_subtest "Show handles subprocess errors"
+cat > notmuch_fail <<EOF
+#!/bin/sh
+echo This is output
+echo This is an error >&2
+exit 1
+EOF
+chmod a+x notmuch_fail
+test_emacs "(let ((notmuch-command \"$PWD/notmuch_fail\"))
+ (with-current-buffer \"*Messages*\" (erase-buffer))
+ (condition-case err
+ (notmuch-show \"*\")
+ (error (message \"%s\" (second err))))
+ (notmuch-test-wait)
+ (with-current-buffer \"*Messages*\"
+ (test-output \"MESSAGES\"))
+ (with-current-buffer \"*Notmuch errors*\"
+ (test-output \"ERROR\"))
+ (test-output))"
+test_expect_equal "$(notmuch_emacs_error_sanitize notmuch_fail OUTPUT MESSAGES ERROR)" "\
+=== OUTPUT ===
+=== MESSAGES ===
+This is an error (see *Notmuch errors* for more details)
+=== ERROR ===
+[XXX]
+This is an error
+command: YYY/notmuch_fail show --format\\=sexp --format-version\\=1 --exclude\\=false \\' \\* \\'
+exit status: 1
+stderr:
+This is an error
+stdout:
+This is output"
+
+
+test_done
--- /dev/null
+#!/usr/bin/env bash
+
+test_description="emacs tree view interface"
+. test-lib.sh
+
+EXPECTED=$TEST_DIRECTORY/tree.expected-output
+
+add_email_corpus
+
+test_begin_subtest "Basic notmuch-tree view in emacs"
+test_emacs '(notmuch-tree "tag:inbox")
+ (notmuch-test-wait)
+ (test-output)
+ (delete-other-windows)'
+test_expect_equal_file OUTPUT $EXPECTED/notmuch-tree-tag-inbox
+
+test_begin_subtest "Refreshed notmuch-tree view in emacs"
+test_emacs '(notmuch-tree "tag:inbox")
+ (notmuch-test-wait)
+ (notmuch-tree-refresh-view)
+ (notmuch-test-wait)
+ (test-output)
+ (delete-other-windows)'
+test_expect_equal_file OUTPUT $EXPECTED/notmuch-tree-tag-inbox
+
+# In the following tag tests we make sure the display is updated
+# correctly and, in a separate test, that the database is updated
+# correctly.
+
+test_begin_subtest "Tag message in notmuch tree view (display)"
+test_emacs '(notmuch-tree "tag:inbox")
+ (notmuch-test-wait)
+ (forward-line)
+ (notmuch-tree-tag (list "+test_tag"))
+ (test-output)
+ (delete-other-windows)'
+test_expect_equal_file OUTPUT $EXPECTED/notmuch-tree-tag-inbox-tagged
+
+test_begin_subtest "Tag message in notmuch tree view (database)"
+output=$(notmuch search --output=messages 'tag:test_tag')
+test_expect_equal "$output" "id:877h1wv7mg.fsf@inf-8657.int-evry.fr"
+
+test_begin_subtest "Untag message in notmuch tree view"
+test_emacs '(notmuch-tree "tag:inbox")
+ (notmuch-test-wait)
+ (forward-line)
+ (notmuch-tree-tag (list "-test_tag"))
+ (test-output)
+ (delete-other-windows)'
+test_expect_equal_file OUTPUT $EXPECTED/notmuch-tree-tag-inbox
+
+test_begin_subtest "Untag message in notmuch tree view (database)"
+output=$(notmuch search --output=messages 'tag:test_tag')
+test_expect_equal "$output" ""
+
+test_begin_subtest "Tag thread in notmuch tree view"
+test_emacs '(notmuch-tree "tag:inbox")
+ (notmuch-test-wait)
+ ;; move to a sizable thread
+ (forward-line 26)
+ (notmuch-tree-tag-thread (list "+test_thread_tag"))
+ (test-output)
+ (delete-other-windows)'
+test_expect_equal_file OUTPUT $EXPECTED/notmuch-tree-tag-inbox-thread-tagged
+
+test_begin_subtest "Tag message in notmuch tree view (database)"
+output=$(notmuch search --output=messages 'tag:test_thread_tag')
+test_expect_equal "$output" \
+"id:87ocn0qh6d.fsf@yoom.home.cworth.org
+id:20091118005040.GA25380@dottiness.seas.harvard.edu
+id:yunaayketfm.fsf@aiko.keithp.com
+id:87fx8can9z.fsf@vertex.dottedmag
+id:20091117203301.GV3165@dottiness.seas.harvard.edu
+id:87iqd9rn3l.fsf@vertex.dottedmag
+id:20091117190054.GU3165@dottiness.seas.harvard.edu"
+
+test_begin_subtest "Untag thread in notmuch tree view"
+test_emacs '(notmuch-tree "tag:inbox")
+ (notmuch-test-wait)
+ ;; move to the same sizable thread as above
+ (forward-line 26)
+ (notmuch-tree-tag-thread (list "-test_thread_tag"))
+ (test-output)
+ (delete-other-windows)'
+test_expect_equal_file OUTPUT $EXPECTED/notmuch-tree-tag-inbox
+
+test_begin_subtest "Untag message in notmuch tree view (database)"
+output=$(notmuch search --output=messages 'tag:test_thread_tag')
+test_expect_equal "$output" ""
+
+test_begin_subtest "Navigation of notmuch-hello to search results"
+test_emacs '(notmuch-hello)
+ (goto-char (point-min))
+ (re-search-forward "inbox")
+ (widget-button-press (1- (point)))
+ (notmuch-test-wait)
+ (notmuch-tree-from-search-current-query)
+ (notmuch-test-wait)
+ (test-output)
+ (delete-other-windows)'
+test_expect_equal_file OUTPUT $EXPECTED/notmuch-tree-tag-inbox
+
+test_begin_subtest "Tree view of a single thread (from search)"
+test_emacs '(notmuch-hello)
+ (goto-char (point-min))
+ (re-search-forward "inbox")
+ (widget-button-press (1- (point)))
+ (notmuch-test-wait)
+ (notmuch-tree-from-search-thread)
+ (notmuch-test-wait)
+ (test-output)
+ (delete-other-windows)'
+test_expect_equal_file OUTPUT $EXPECTED/notmuch-tree-single-thread
+
+test_begin_subtest "Tree view of a single thread (from show)"
+test_emacs '(notmuch-hello)
+ (goto-char (point-min))
+ (re-search-forward "inbox")
+ (widget-button-press (1- (point)))
+ (notmuch-test-wait)
+ (notmuch-search-show-thread)
+ (notmuch-tree-from-show-current-query)
+ (notmuch-test-wait)
+ (test-output)
+ (delete-other-windows)'
+test_expect_equal_file OUTPUT $EXPECTED/notmuch-tree-single-thread
+
+test_begin_subtest "Message window of tree view"
+test_emacs '(notmuch-hello)
+ (goto-char (point-min))
+ (re-search-forward "inbox")
+ (widget-button-press (1- (point)))
+ (notmuch-test-wait)
+ (notmuch-search-next-thread)
+ (notmuch-tree-from-search-thread)
+ (notmuch-test-wait)
+ (select-window notmuch-tree-message-window)
+ (test-output)
+ (delete-other-windows)'
+cp OUTPUT /tmp/mjwout
+test_expect_equal_file OUTPUT $EXPECTED/notmuch-tree-show-window
+
+test_begin_subtest "Stash id"
+output=$(test_emacs '(notmuch-tree "id:1258498485-sup-142@elly")
+ (notmuch-test-wait)
+ (notmuch-show-stash-message-id)')
+test_expect_equal "$output" "\"Stashed: id:1258498485-sup-142@elly\""
+
+test_begin_subtest "Move to next matching message"
+output=$(test_emacs '(notmuch-tree "from:cworth")
+ (notmuch-test-wait)
+ (notmuch-tree-next-matching-message)
+ (notmuch-show-stash-message-id)')
+test_expect_equal "$output" "\"Stashed: id:878we4qdqf.fsf@yoom.home.cworth.org\""
+
+test_begin_subtest "Move to next thread"
+output=$(test_emacs '(notmuch-tree "tag:inbox")
+ (notmuch-test-wait)
+ (forward-line 26)
+ (notmuch-tree-next-thread)
+ (notmuch-show-stash-message-id)')
+test_expect_equal "$output" "\"Stashed: id:1258471718-6781-1-git-send-email-dottedmag@dottedmag.net\""
+
+test_begin_subtest "Move to previous thread"
+output=$(test_emacs '(notmuch-tree "tag:inbox")
+ (notmuch-test-wait)
+ (forward-line 26)
+ (notmuch-tree-prev-thread)
+ (notmuch-show-stash-message-id)')
+test_expect_equal "$output" "\"Stashed: id:20091117190054.GU3165@dottiness.seas.harvard.edu\""
+
+test_begin_subtest "Move to previous previous thread"
+output=$(test_emacs '(notmuch-tree "tag:inbox")
+ (notmuch-test-wait)
+ (forward-line 26)
+ (notmuch-tree-prev-thread)
+ (notmuch-tree-prev-thread)
+ (notmuch-show-stash-message-id)')
+test_expect_equal "$output" "\"Stashed: id:1258493565-13508-1-git-send-email-keithp@keithp.com\""
+
+test_done
--- /dev/null
+#!/usr/bin/env bash
+test_description='messages with missing headers'
+. ./test-lib.sh
+
+# Notmuch requires at least one of from, subject, or to or it will
+# ignore the file. Generate two messages so that together they cover
+# all possible missing headers. We also give one of the messages a
+# date to ensure stable result ordering.
+
+cat <<EOF > "${MAIL_DIR}/msg-2"
+To: Notmuch Test Suite <test_suite@notmuchmail.org>
+Date: Fri, 05 Jan 2001 15:43:57 +0000
+
+Body
+EOF
+
+cat <<EOF > "${MAIL_DIR}/msg-1"
+From: Notmuch Test Suite <test_suite@notmuchmail.org>
+
+Body
+EOF
+
+NOTMUCH_NEW
+
+test_begin_subtest "Search: text"
+output=$(notmuch search '*' | notmuch_search_sanitize)
+test_expect_equal "$output" "\
+thread:XXX 2001-01-05 [1/1] (null); (inbox unread)
+thread:XXX 1970-01-01 [1/1] Notmuch Test Suite; (inbox unread)"
+
+test_begin_subtest "Search: json"
+output=$(notmuch search --format=json '*' | notmuch_search_sanitize)
+test_expect_equal_json "$output" '
+[
+ {
+ "authors": "",
+ "date_relative": "2001-01-05",
+ "matched": 1,
+ "subject": "",
+ "tags": [
+ "inbox",
+ "unread"
+ ],
+ "thread": "XXX",
+ "timestamp": 978709437,
+ "total": 1,
+ "query": ["id:notmuch-sha1-7a6e4eac383ef958fcd3ebf2143db71b8ff01161", null]
+ },
+ {
+ "authors": "Notmuch Test Suite",
+ "date_relative": "1970-01-01",
+ "matched": 1,
+ "subject": "",
+ "tags": [
+ "inbox",
+ "unread"
+ ],
+ "thread": "XXX",
+ "timestamp": 0,
+ "total": 1,
+ "query": ["id:notmuch-sha1-ca55943aff7a72baf2ab21fa74fab3d632401334", null]
+ }
+]'
+
+test_begin_subtest "Show: text"
+output=$(notmuch show '*' | notmuch_show_sanitize)
+test_expect_equal "$output" "\
+\fmessage{ id:notmuch-sha1-7a6e4eac383ef958fcd3ebf2143db71b8ff01161 depth:0 match:1 excluded:0 filename:/XXX/mail/msg-2
+\fheader{
+ (2001-01-05) (inbox unread)
+Subject: (null)
+From: (null)
+To: Notmuch Test Suite <test_suite@notmuchmail.org>
+Date: Fri, 05 Jan 2001 15:43:57 +0000
+\fheader}
+\fbody{
+\fpart{ ID: 1, Content-type: text/plain
+Body
+\fpart}
+\fbody}
+\fmessage}
+\fmessage{ id:notmuch-sha1-ca55943aff7a72baf2ab21fa74fab3d632401334 depth:0 match:1 excluded:0 filename:/XXX/mail/msg-1
+\fheader{
+Notmuch Test Suite <test_suite@notmuchmail.org> (1970-01-01) (inbox unread)
+Subject: (null)
+From: Notmuch Test Suite <test_suite@notmuchmail.org>
+Date: Thu, 01 Jan 1970 00:00:00 +0000
+\fheader}
+\fbody{
+\fpart{ ID: 1, Content-type: text/plain
+Body
+\fpart}
+\fbody}
+\fmessage}"
+
+test_begin_subtest "Show: json"
+output=$(notmuch show --format=json '*' | notmuch_json_show_sanitize)
+expected=$(notmuch_json_show_sanitize <<EOF
+[
+ [
+ [
+ {
+ "body": [
+ {
+ "content": "Body\n",
+ "content-type": "text/plain",
+ "id": 1
+ }
+ ],
+ "date_relative": "2001-01-05",
+ "excluded": false,
+ "filename": "YYYYY",
+ "headers": {
+ "Date": "Fri, 05 Jan 2001 15:43:57 +0000",
+ "From": "",
+ "Subject": "",
+ "To": "Notmuch Test Suite <test_suite@notmuchmail.org>"
+ },
+ "id": "XXXXX",
+ "match": true,
+ "tags": [
+ "inbox",
+ "unread"
+ ],
+ "timestamp": 978709437
+ },
+ []
+ ]
+ ],
+ [
+ [
+ {
+ "body": [
+ {
+ "content": "Body\n",
+ "content-type": "text/plain",
+ "id": 1
+ }
+ ],
+ "date_relative": "1970-01-01",
+ "excluded": false,
+ "filename": "YYYYY",
+ "headers": {
+ "Date": "Thu, 01 Jan 1970 00:00:00 +0000",
+ "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
+ "Subject": ""
+ },
+ "id": "XXXXX",
+ "match": true,
+ "tags": [
+ "inbox",
+ "unread"
+ ],
+ "timestamp": 0
+ },
+ []
+ ]
+ ]
+]
+EOF
+)
+test_expect_equal_json "$output" "$expected"
+
+test_done
--- /dev/null
+#!/usr/bin/env bash
+test_description="hex encoding and decoding"
+. ./test-lib.sh
+
+test_begin_subtest "round trip"
+find $TEST_DIRECTORY/corpus -type f -print | sort | xargs cat > EXPECTED
+$TEST_DIRECTORY/hex-xcode --direction=encode < EXPECTED | $TEST_DIRECTORY/hex-xcode --direction=decode > OUTPUT
+test_expect_equal_file OUTPUT EXPECTED
+
+test_begin_subtest "punctuation"
+tag1='comic_swear=$&^%$^%\\//-+$^%$'
+tag_enc1=$($TEST_DIRECTORY/hex-xcode --direction=encode "$tag1")
+test_expect_equal "$tag_enc1" "comic_swear=%24%26%5e%25%24%5e%25%5c%5c%2f%2f-+%24%5e%25%24"
+
+test_begin_subtest "round trip newlines"
+printf 'this\n tag\t has\n spaces\n' > EXPECTED.$test_count
+$TEST_DIRECTORY/hex-xcode --direction=encode < EXPECTED.$test_count |\
+ $TEST_DIRECTORY/hex-xcode --direction=decode > OUTPUT.$test_count
+test_expect_equal_file EXPECTED.$test_count OUTPUT.$test_count
+
+test_begin_subtest "round trip 8bit chars"
+echo '%c3%91%c3%a5%c3%b0%c3%a3%c3%a5%c3%a9-%c3%8f%c3%8a' > EXPECTED.$test_count
+$TEST_DIRECTORY/hex-xcode --direction=decode < EXPECTED.$test_count |\
+ $TEST_DIRECTORY/hex-xcode --direction=encode > OUTPUT.$test_count
+test_expect_equal_file EXPECTED.$test_count OUTPUT.$test_count
+
+test_begin_subtest "round trip (in-place)"
+find $TEST_DIRECTORY/corpus -type f -print | sort | xargs cat > EXPECTED
+$TEST_DIRECTORY/hex-xcode --in-place --direction=encode < EXPECTED |\
+ $TEST_DIRECTORY/hex-xcode --in-place --direction=decode > OUTPUT
+test_expect_equal_file OUTPUT EXPECTED
+
+test_begin_subtest "punctuation (in-place)"
+tag1='comic_swear=$&^%$^%\\//-+$^%$'
+tag_enc1=$($TEST_DIRECTORY/hex-xcode --in-place --direction=encode "$tag1")
+test_expect_equal "$tag_enc1" "comic_swear=%24%26%5e%25%24%5e%25%5c%5c%2f%2f-+%24%5e%25%24"
+
+test_begin_subtest "round trip newlines (in-place)"
+printf 'this\n tag\t has\n spaces\n' > EXPECTED.$test_count
+$TEST_DIRECTORY/hex-xcode --in-place --direction=encode < EXPECTED.$test_count |\
+ $TEST_DIRECTORY/hex-xcode --in-place --direction=decode > OUTPUT.$test_count
+test_expect_equal_file EXPECTED.$test_count OUTPUT.$test_count
+
+test_begin_subtest "round trip 8bit chars (in-place)"
+echo '%c3%91%c3%a5%c3%b0%c3%a3%c3%a5%c3%a9-%c3%8f%c3%8a' > EXPECTED.$test_count
+$TEST_DIRECTORY/hex-xcode --in-place --direction=decode < EXPECTED.$test_count |\
+ $TEST_DIRECTORY/hex-xcode --in-place --direction=encode > OUTPUT.$test_count
+test_expect_equal_file EXPECTED.$test_count OUTPUT.$test_count
+
+test_done
--- /dev/null
+#!/usr/bin/env bash
+test_description="date/time parser module"
+. ./test-lib.sh
+
+# Sanity/smoke tests for the date/time parser independent of notmuch
+
+_date ()
+{
+ date -d "$*" +%s
+}
+
+_parse_time ()
+{
+ ${TEST_DIRECTORY}/parse-time --format=%s "$*"
+}
+
+test_begin_subtest "date(1) default format without TZ code"
+test_expect_equal "$(_parse_time Fri Aug 3 23:06:06 2012)" "$(_date Fri Aug 3 23:06:06 2012)"
+
+test_begin_subtest "date(1) --rfc-2822 format"
+test_expect_equal "$(_parse_time Fri, 03 Aug 2012 23:07:46 +0100)" "$(_date Fri, 03 Aug 2012 23:07:46 +0100)"
+
+test_begin_subtest "date(1) --rfc=3339=seconds format"
+test_expect_equal "$(_parse_time 2012-08-03 23:09:37+03:00)" "$(_date 2012-08-03 23:09:37+03:00)"
+
+test_begin_subtest "Date parser tests"
+REFERENCE=$(_date Tue Jan 11 11:11:00 +0000 2011)
+cat <<EOF > INPUT
+now ==> Tue Jan 11 11:11:00 +0000 2011
+2010-1-1 ==> ERROR: DATEFORMAT
+Jan 2 ==> Sun Jan 02 11:11:00 +0000 2011
+Mon ==> Mon Jan 10 11:11:00 +0000 2011
+last Friday ==> ERROR: FORMAT
+2 hours ago ==> Tue Jan 11 09:11:00 +0000 2011
+last month ==> Sat Dec 11 11:11:00 +0000 2010
+month ago ==> Sat Dec 11 11:11:00 +0000 2010
+two mo ==> Thu Nov 11 11:11:00 +0000 2010
+3M ==> Mon Oct 11 11:11:00 +0000 2010
+4-mont ==> Sat Sep 11 11:11:00 +0000 2010
+5m ==> Tue Jan 11 11:06:00 +0000 2011
+dozen mi ==> Tue Jan 11 10:59:00 +0000 2011
+8am ==> Tue Jan 11 08:00:00 +0000 2011
+9:15 ==> Tue Jan 11 09:15:00 +0000 2011
+12:34 ==> Tue Jan 11 12:34:00 +0000 2011
+monday ==> Mon Jan 10 11:11:00 +0000 2011
+yesterday ==> Mon Jan 10 11:11:00 +0000 2011
+tomorrow ==> ERROR: KEYWORD
+ ==> Tue Jan 11 11:11:00 +0000 2011 # empty string is reference time
+
+Aug 3 23:06:06 2012 ==> Fri Aug 03 23:06:06 +0000 2012 # date(1) default format without TZ code
+Fri, 03 Aug 2012 23:07:46 +0100 ==> Fri Aug 03 22:07:46 +0000 2012 # rfc-2822
+2012-08-03 23:09:37+03:00 ==> Fri Aug 03 20:09:37 +0000 2012 # rfc-3339 seconds
+
+10s ==> Tue Jan 11 11:10:50 +0000 2011
+19701223s ==> Fri May 28 10:37:17 +0000 2010
+19701223 ==> Wed Dec 23 11:11:00 +0000 1970
+
+19701223 +0100 ==> Wed Dec 23 11:11:00 +0000 1970 # Timezone is ignored without an error
+
+today ==^^> Wed Jan 12 00:00:00 +0000 2011
+today ==^> Tue Jan 11 23:59:59 +0000 2011
+today ==_> Tue Jan 11 00:00:00 +0000 2011
+
+this week ==^^> Sun Jan 16 00:00:00 +0000 2011
+this week ==^> Sat Jan 15 23:59:59 +0000 2011
+this week ==_> Sun Jan 09 00:00:00 +0000 2011
+
+two months ago ==> Thu Nov 11 11:11:00 +0000 2010
+two months ==> Thu Nov 11 11:11:00 +0000 2010
+
+@1348569850 ==> Tue Sep 25 10:44:10 +0000 2012
+@10 ==> Thu Jan 01 00:00:10 +0000 1970
+EOF
+
+${TEST_DIRECTORY}/parse-time --ref=${REFERENCE} < INPUT > OUTPUT
+test_expect_equal_file INPUT OUTPUT
+
+test_done
--- /dev/null
+#!/usr/bin/env bash
+test_description="date:since..until queries"
+. ./test-lib.sh
+
+add_email_corpus
+
+test_begin_subtest "Absolute date range"
+output=$(notmuch search date:2010-12-16..12/16/2010 | notmuch_search_sanitize)
+test_expect_equal "$output" "thread:XXX 2010-12-16 [1/1] Olivier Berger; Essai accentué (inbox unread)"
+
+test_begin_subtest "Absolute time range with TZ"
+notmuch search date:18-Nov-2009_02:19:26-0800..2009-11-18_04:49:52-06:00 | notmuch_search_sanitize > OUTPUT
+cat <<EOF >EXPECTED
+thread:XXX 2009-11-18 [1/3] Carl Worth| Jan Janak; [notmuch] What a great idea! (inbox unread)
+thread:XXX 2009-11-18 [1/2] Carl Worth| Jan Janak; [notmuch] [PATCH] Older versions of install do not support -C. (inbox unread)
+thread:XXX 2009-11-18 [1/3] Carl Worth| Aron Griffis, Keith Packard; [notmuch] archive (inbox unread)
+thread:XXX 2009-11-18 [1/2] Carl Worth| Keith Packard; [notmuch] [PATCH] Make notmuch-show 'X' (and 'x') commands remove inbox (and unread) tags (inbox unread)
+EOF
+test_expect_equal_file OUTPUT EXPECTED
+
+test_done
--- /dev/null
+#!/usr/bin/env bash
+#
+# Copyright (c) 2013 Aaron Ecay
+#
+
+test_description='test of proper handling of in-reply-to and references headers'
+
+# This test makes sure that the thread structure in the notmuch
+# database is constructed properly, even in the presence of
+# non-RFC-compliant headers'
+
+. ./test-lib.sh
+
+test_begin_subtest "Use References when In-Reply-To is broken"
+add_message '[id]="foo@one.com"' \
+ '[subject]=one'
+add_message '[in-reply-to]="mumble"' \
+ '[references]="<foo@one.com>"' \
+ '[subject]="Re: one"'
+output=$(notmuch show --format=json 'subject:one' | notmuch_json_show_sanitize)
+expected='[[[{"id": "foo@one.com",
+ "match": true,
+ "excluded": false,
+ "filename": "YYYYY",
+ "timestamp": 978709437,
+ "date_relative": "2001-01-05",
+ "tags": ["inbox", "unread"],
+ "headers": {"Subject": "one",
+ "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
+ "To": "Notmuch Test Suite <test_suite@notmuchmail.org>",
+ "Date": "Fri, 05 Jan 2001 15:43:57 +0000"},
+ "body": [{"id": 1,
+ "content-type": "text/plain",
+ "content": "This is just a test message (#1)\n"}]},
+ [[{"id": "msg-002@notmuch-test-suite",
+ "match": true, "excluded": false,
+ "filename": "YYYYY",
+ "timestamp": 978709437, "date_relative": "2001-01-05",
+ "tags": ["inbox", "unread"], "headers": {"Subject": "Re: one",
+ "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
+ "To": "Notmuch Test Suite <test_suite@notmuchmail.org>",
+ "Date": "Fri, 05 Jan 2001 15:43:57 +0000"},
+ "body": [{"id": 1, "content-type": "text/plain",
+ "content": "This is just a test message (#2)\n"}]}, []]]]]]'
+expected=`echo "$expected" | notmuch_json_show_sanitize`
+test_expect_equal_json "$output" "$expected"
+
+test_begin_subtest "Prefer References to In-Reply-To"
+add_message '[id]="foo@two.com"' \
+ '[subject]=two'
+add_message '[in-reply-to]="<bar@baz.com>"' \
+ '[references]="<foo@two.com>"' \
+ '[subject]="Re: two"'
+output=$(notmuch show --format=json 'subject:two' | notmuch_json_show_sanitize)
+expected='[[[{"id": "foo@two.com",
+ "match": true, "excluded": false,
+ "filename": "YYYYY",
+ "timestamp": 978709437, "date_relative": "2001-01-05", "tags": ["inbox", "unread"],
+ "headers": {"Subject": "two",
+ "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
+ "To": "Notmuch Test Suite <test_suite@notmuchmail.org>",
+ "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"}]},
+ [[{"id": "msg-004@notmuch-test-suite", "match": true, "excluded": false,
+ "filename": "YYYYY",
+ "timestamp": 978709437, "date_relative": "2001-01-05", "tags": ["inbox", "unread"],
+ "headers": {"Subject": "Re: two",
+ "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
+ "To": "Notmuch Test Suite <test_suite@notmuchmail.org>",
+ "Date": "Fri, 05 Jan 2001 15:43:57 +0000"},
+ "body": [{"id": 1,
+ "content-type": "text/plain", "content": "This is just a test message (#4)\n"}]},
+ []]]]]]'
+expected=`echo "$expected" | notmuch_json_show_sanitize`
+test_expect_equal_json "$output" "$expected"
+
+test_begin_subtest "Use In-Reply-To when no References"
+add_message '[id]="foo@three.com"' \
+ '[subject]="three"'
+add_message '[in-reply-to]="<foo@three.com>"' \
+ '[subject]="Re: three"'
+output=$(notmuch show --format=json 'subject:three' | notmuch_json_show_sanitize)
+expected='[[[{"id": "foo@three.com", "match": true, "excluded": false,
+ "filename": "YYYYY",
+ "timestamp": 978709437, "date_relative": "2001-01-05", "tags": ["inbox", "unread"],
+ "headers": {"Subject": "three",
+ "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
+ "To": "Notmuch Test Suite <test_suite@notmuchmail.org>",
+ "Date": "Fri, 05 Jan 2001 15:43:57 +0000"}, "body": [{"id": 1,
+ "content-type": "text/plain", "content": "This is just a test message (#5)\n"}]},
+ [[{"id": "msg-006@notmuch-test-suite", "match": true, "excluded": false,
+ "filename": "YYYYY",
+ "timestamp": 978709437, "date_relative": "2001-01-05", "tags": ["inbox", "unread"],
+ "headers": {"Subject": "Re: three",
+ "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
+ "To": "Notmuch Test Suite <test_suite@notmuchmail.org>",
+ "Date": "Fri, 05 Jan 2001 15:43:57 +0000"}, "body": [{"id": 1,
+ "content-type": "text/plain", "content": "This is just a test message (#6)\n"}]},
+ []]]]]]'
+expected=`echo "$expected" | notmuch_json_show_sanitize`
+test_expect_equal_json "$output" "$expected"
+
+test_begin_subtest "Use last Reference"
+add_message '[id]="foo@four.com"' \
+ '[subject]="four"'
+add_message '[id]="bar@four.com"' \
+ '[subject]="not-four"'
+add_message '[in-reply-to]="<baz@four.com>"' \
+ '[references]="<baz@four.com> <foo@four.com>"' \
+ '[subject]="neither"'
+output=$(notmuch show --format=json 'subject:four' | notmuch_json_show_sanitize)
+expected='[[[{"id": "foo@four.com", "match": true, "excluded": false,
+ "filename": "YYYYY",
+ "timestamp": 978709437, "date_relative": "2001-01-05", "tags": ["inbox", "unread"],
+ "headers": {"Subject": "four",
+ "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
+ "To": "Notmuch Test Suite <test_suite@notmuchmail.org>",
+ "Date": "Fri, 05 Jan 2001 15:43:57 +0000"}, "body": [{"id": 1,
+ "content-type": "text/plain", "content": "This is just a test message (#7)\n"}]},
+ [[{"id": "msg-009@notmuch-test-suite", "match": false, "excluded": false,
+ "filename": "YYYYY",
+ "timestamp": 978709437, "date_relative": "2001-01-05", "tags": ["inbox", "unread"],
+ "headers": {"Subject": "neither",
+ "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
+ "To": "Notmuch Test Suite <test_suite@notmuchmail.org>",
+ "Date": "Fri, 05 Jan 2001 15:43:57 +0000"}, "body": [{"id": 1,
+ "content-type": "text/plain", "content": "This is just a test message (#9)\n"}]},
+ []]]]], [[{"id": "bar@four.com", "match": true, "excluded": false,
+ "filename": "YYYYY",
+ "timestamp": 978709437, "date_relative": "2001-01-05", "tags": ["inbox", "unread"],
+ "headers": {"Subject": "not-four",
+ "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
+ "To": "Notmuch Test Suite <test_suite@notmuchmail.org>",
+ "Date": "Fri, 05 Jan 2001 15:43:57 +0000"}, "body": [{"id": 1,
+ "content-type": "text/plain", "content": "This is just a test message (#8)\n"}]}, []]]]'
+expected=`echo "$expected" | notmuch_json_show_sanitize`
+test_expect_equal_json "$output" "$expected"
+
+
+test_done
--- /dev/null
+#!/usr/bin/env bash
+test_description='"notmuch show"'
+
+. ./test-lib.sh
+
+add_email_corpus
+
+test_begin_subtest "exit code for show invalid query"
+notmuch show foo..
+exit_code=$?
+test_expect_equal 1 $exit_code
+
+test_done
+++ /dev/null
-#!/usr/bin/env bash
-test_description="argument parsing"
-. ./test-lib.sh
-
-test_begin_subtest "sanity check"
-$TEST_DIRECTORY/arg-test pos1 --keyword=one --string=foo pos2 --int=7 > OUTPUT
-cat <<EOF > EXPECTED
-keyword 1
-int 7
-string foo
-positional arg 1 pos1
-positional arg 2 pos2
-EOF
-test_expect_equal_file OUTPUT EXPECTED
-
-test_done
+++ /dev/null
-#!/usr/bin/env bash
-test_description='atomicity'
-. ./test-lib.sh
-
-# This script tests the effects of killing and restarting "notmuch
-# new" at arbitrary points. If notmuch new is properly atomic, the
-# final database contents should be the same regardless of when (or
-# if) it is killed and restarted.
-
-if test_require_external_prereq gdb; then
-
-# Create a maildir structure to also stress flag synchronization
- mkdir $MAIL_DIR/cur
- mkdir $MAIL_DIR/new
- mkdir $MAIL_DIR/tmp
- mkdir $MAIL_DIR/.remove-dir
-
- # Prepare the initial database
- generate_message [subject]='Duplicate' [filename]='duplicate:2,' [dir]=cur
- generate_message [subject]='Remove' [filename]='remove:2,' [dir]=cur
- generate_message [subject]='"Remove duplicate"' [filename]='remove-duplicate:2,' [dir]=cur
- cp $MAIL_DIR/cur/remove-duplicate:2, $MAIL_DIR/cur/remove-duplicate-copy:2,
- generate_message [subject]='Rename' [filename]='rename:2,' [dir]=cur
- generate_message [subject]='"Rename duplicate"' [filename]='rename-duplicate:2,' [dir]=cur
- generate_message [subject]='"Move 1"' [filename]='move1:2,' [dir]=cur
- generate_message [subject]='"Move 2"' [filename]='move2:2,' [dir]=new
- generate_message [subject]='Flag' [filename]='flag:2,' [dir]=cur
- generate_message [subject]='"Flag duplicate"' [filename]='flag-duplicate:2,' [dir]=cur
- cp $MAIL_DIR/cur/flag-duplicate:2, $MAIL_DIR/cur/flag-duplicate-copy:2,F
- generate_message [subject]='"Remove directory"' [filename]='remove-directory:2,' [dir]=.remove-dir
- generate_message [subject]='"Remove directory duplicate"' [filename]='remove-directory-duplicate:2,' [dir]=.remove-dir
- cp $MAIL_DIR/.remove-dir/remove-directory-duplicate:2, $MAIL_DIR/cur/
- notmuch new > /dev/null
-
- # Make all maildir changes, but *don't* update the database
- generate_message [subject]='Added' [filename]='added:2,' [dir]=cur
- cp $MAIL_DIR/cur/duplicate:2, $MAIL_DIR/cur/duplicate-copy:2,
- generate_message [subject]='"Add duplicate"' [filename]='add-duplicate:2,' [dir]=cur
- generate_message [subject]='"Add duplicate copy"' [filename]='add-duplicate-copy:2,' [dir]=cur
- rm $MAIL_DIR/cur/remove:2,
- rm $MAIL_DIR/cur/remove-duplicate-copy:2,
- mv $MAIL_DIR/cur/rename:2, $MAIL_DIR/cur/renamed:2,
- mv $MAIL_DIR/cur/rename-duplicate:2, $MAIL_DIR/cur/renamed-duplicate:2,
- mv $MAIL_DIR/cur/move1:2, $MAIL_DIR/new/move1:2,
- mv $MAIL_DIR/new/move2:2, $MAIL_DIR/cur/move2:2,
- mv $MAIL_DIR/cur/flag:2, $MAIL_DIR/cur/flag:2,F
- rm $MAIL_DIR/cur/flag-duplicate-copy:2,F
- rm $MAIL_DIR/.remove-dir/remove-directory:2,
- rm $MAIL_DIR/.remove-dir/remove-directory-duplicate:2,
- rmdir $MAIL_DIR/.remove-dir
-
- # Prepare a snapshot of the updated maildir. The gdb script will
- # update the database in this snapshot as it goes.
- cp -a $MAIL_DIR $MAIL_DIR.snap
- cp ${NOTMUCH_CONFIG} ${NOTMUCH_CONFIG}.snap
- NOTMUCH_CONFIG=${NOTMUCH_CONFIG}.snap notmuch config set database.path $MAIL_DIR.snap
-
-
-
- # Execute notmuch new and, at every call to rename, snapshot the
- # database, run notmuch new again on the snapshot, and capture the
- # results of search.
- #
- # -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 >/dev/null 2>/dev/null
-
- # Get the final, golden output
- notmuch search '*' > expected
-
- # Check output against golden output
- outcount=$(cat outcount)
- echo -n > searchall
- echo -n > expectall
- for ((i = 0; i < $outcount; i++)); do
- if ! cmp -s search.$i expected; then
- # Find the range of interruptions that match this output
- for ((end = $i + 1 ; end < $outcount; end++)); do
- if ! cmp -s search.$i search.$end; then
- break
- fi
- done
- echo "When interrupted after $test/backtrace.$(expr $i - 1) (abort points $i-$(expr $end - 1))" >> searchall
- cat search.$i >> searchall
- cat expected >> expectall
- echo >> searchall
- echo >> expectall
-
- i=$(expr $end - 1)
- fi
- done
-fi
-
-test_begin_subtest '"notmuch new" is idempotent under arbitrary aborts'
-test_expect_equal_file searchall expectall
-
-test_expect_success "detected $outcount>10 abort points" "test $outcount -gt 10"
-
-test_done
+++ /dev/null
-#!/usr/bin/env bash
-test_description="author reordering;"
-. ./test-lib.sh
-
-test_begin_subtest "Adding parent message"
-generate_message [body]=findme [id]=new-parent-id [subject]=author-reorder-threadtest '[from]="User <user@example.com>"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"'
-output=$(NOTMUCH_NEW)
-test_expect_equal "$output" "Added 1 new message to the database."
-
-test_begin_subtest "Adding initial child message"
-generate_message [body]=findme "[in-reply-to]=\<new-parent-id\>" [subject]=author-reorder-threadtest '[from]="User1 <user1@example.com>"' '[date]="Sat, 01 Jan 2000 12:01:00 -0000"'
-output=$(NOTMUCH_NEW)
-test_expect_equal "$output" "Added 1 new message to the database."
-
-test_begin_subtest "Adding second child message"
-generate_message [body]=findme "[in-reply-to]=\<new-parent-id\>" [subject]=author-reorder-threadtest '[from]="User2 <user2@example.com>"' '[date]="Sat, 01 Jan 2000 12:02:00 -0000"'
-output=$(NOTMUCH_NEW)
-test_expect_equal "$output" "Added 1 new message to the database."
-
-test_begin_subtest "Searching when all three messages match"
-output=$(notmuch search findme | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2000-01-01 [3/3] User, User1, User2; author-reorder-threadtest (inbox unread)"
-
-test_begin_subtest "Searching when two messages match"
-output=$(notmuch search User1 or User2 | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2000-01-01 [2/3] User1, User2| User; author-reorder-threadtest (inbox unread)"
-
-test_begin_subtest "Searching when only one message matches"
-output=$(notmuch search User2 | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2000-01-01 [1/3] User2| User, User1; author-reorder-threadtest (inbox unread)"
-
-test_begin_subtest "Searching when only first message matches"
-output=$(notmuch search User | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2000-01-01 [1/3] User| User1, User2; author-reorder-threadtest (inbox unread)"
-
-test_begin_subtest "Adding duplicate author"
-generate_message [body]=findme "[in-reply-to]=\<new-parent-id\>" [subject]=author-reorder-threadtest '[from]="User1 <user1@example.com>"' '[date]="Sat, 01 Jan 2000 12:03:00 -0000"'
-output=$(NOTMUCH_NEW)
-test_expect_equal "$output" "Added 1 new message to the database."
-
-test_begin_subtest "Searching when all four messages match"
-output=$(notmuch search findme | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2000-01-01 [4/4] User, User1, User2; author-reorder-threadtest (inbox unread)"
-
-test_begin_subtest "Adding non-monotonic child message"
-generate_message [body]=findme "[in-reply-to]=\<new-parent-id\>" [subject]=author-reorder-threadtest '[from]="User0 <user0@example.com>"' '[date]="Sat, 01 Jan 2000 11:00:00 -0000"'
-output=$(NOTMUCH_NEW)
-test_expect_equal "$output" "Added 1 new message to the database."
-
-test_begin_subtest "Searching non-monotonic messages (oldest-first)"
-output=$(notmuch search --sort=oldest-first findme | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2000-01-01 [5/5] User0, User, User1, User2; author-reorder-threadtest (inbox unread)"
-
-test_begin_subtest "Searching non-monotonic messages (newest-first)"
-output=$(notmuch search --sort=newest-first findme | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2000-01-01 [5/5] User0, User, User1, User2; author-reorder-threadtest (inbox unread)"
-
-test_done
+++ /dev/null
-#!/usr/bin/env bash
-#
-# Copyright (c) 2005 Junio C Hamano
-#
-
-test_description='the test framework itself.'
-
-################################################################
-# It appears that people try to run tests without building...
-
-if ! test -x ../notmuch
-then
- echo >&2 'You do not seem to have built notmuch yet.'
- exit 1
-fi
-
-. ./test-lib.sh
-
-################################################################
-# Test harness
-test_expect_success 'success is reported like this' '
- :
-'
-test_set_prereq HAVEIT
-haveit=no
-test_expect_success HAVEIT 'test runs if prerequisite is satisfied' '
- test_have_prereq HAVEIT &&
- haveit=yes
-'
-
-clean=no
-test_expect_success 'tests clean up after themselves' '
- test_when_finished clean=yes
-'
-
-cleaner=no
-test_expect_code 1 'tests clean up even after a failure' '
- test_when_finished cleaner=yes &&
- (exit 1)
-'
-
-if test $clean$cleaner != yesyes
-then
- say "bug in test framework: cleanup commands do not work reliably"
- exit 1
-fi
-
-test_expect_code 2 'failure to clean up causes the test to fail' '
- test_when_finished "(exit 2)"
-'
-
-# Ensure that all tests are being run
-test_begin_subtest 'Ensure that all available tests will be run by notmuch-test'
-eval $(sed -n -e '/^TESTS="$/,/^"$/p' $TEST_DIRECTORY/notmuch-test)
-tests_in_suite=$(for i in $TESTS; do echo $i; done | sort)
-available=$(find "$TEST_DIRECTORY" -maxdepth 1 -type f \
- '(' -perm -100 -o -perm -10 -o -perm -1 ')' \
- ! -name aggregate-results.sh \
- ! -name arg-test \
- ! -name hex-xcode \
- ! -name notmuch-test \
- ! -name parse-time \
- ! -name random-corpus \
- ! -name smtp-dummy \
- ! -name symbol-test \
- ! -name test-verbose \
- | sed 's,.*/,,' | sort)
-test_expect_equal "$tests_in_suite" "$available"
-
-EXPECTED=$TEST_DIRECTORY/test.expected-output
-suppress_diff_date() {
- sed -e 's/\(.*\-\-\- test-verbose\.4\.\expected\).*/\1/' \
- -e 's/\(.*\+\+\+ test-verbose\.4\.\output\).*/\1/'
-}
-
-test_begin_subtest "Ensure that test output is suppressed unless the test fails"
-output=$(cd $TEST_DIRECTORY; ./test-verbose 2>&1 | suppress_diff_date)
-expected=$(cat $EXPECTED/test-verbose-no | suppress_diff_date)
-test_expect_equal "$output" "$expected"
-
-test_begin_subtest "Ensure that -v does not suppress test output"
-output=$(cd $TEST_DIRECTORY; ./test-verbose -v 2>&1 | suppress_diff_date)
-expected=$(cat $EXPECTED/test-verbose-yes | suppress_diff_date)
-# Do not include the results of test-verbose in totals
-rm $TEST_DIRECTORY/test-results/test-verbose
-rm -r $TEST_DIRECTORY/tmp.test-verbose
-test_expect_equal "$output" "$expected"
-
-
-################################################################
-# Test mail store prepared in test-lib.sh
-
-test_expect_success \
- 'test that mail store was created' \
- 'test -d "${MAIL_DIR}"'
-
-
-find "${MAIL_DIR}" -type f -print >should-be-empty
-test_expect_success \
- 'mail store should be empty' \
- 'cmp -s /dev/null should-be-empty'
-
-test_expect_success \
- 'NOTMUCH_CONFIG is set and points to an existing file' \
- 'test -f "${NOTMUCH_CONFIG}"'
-
-test_expect_success \
- 'PATH is set to this repository' \
- 'test "`echo $PATH|cut -f1 -d: | sed -e 's,/test/valgrind/bin$,,'`" = "`dirname ${TEST_DIRECTORY}`"'
-
-test_done
+++ /dev/null
-#!/usr/bin/env bash
-test_description='"notmuch compact"'
-. ./test-lib.sh
-
-add_message '[subject]=One'
-add_message '[subject]=Two'
-add_message '[subject]=Three'
-
-notmuch tag +tag1 \*
-notmuch tag +tag2 subject:Two
-notmuch tag -tag1 +tag3 subject:Three
-
-test_expect_success "Running compact" "notmuch compact --backup=${TEST_DIRECTORY}/xapian.old"
-
-test_begin_subtest "Compact preserves database"
-output=$(notmuch search \* | notmuch_search_sanitize)
-test_expect_equal "$output" "\
-thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; One (inbox tag1 unread)
-thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Two (inbox tag1 tag2 unread)
-thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Three (inbox tag3 unread)"
-
-test_expect_success 'Restoring Backup' \
- 'rm -Rf ${MAIL_DIR}/.notmuch/xapian &&
- mv ${TEST_DIRECTORY}/xapian.old ${MAIL_DIR}/.notmuch/xapian'
-
-test_begin_subtest "Checking restored backup"
-output=$(notmuch search \* | notmuch_search_sanitize)
-test_expect_equal "$output" "\
-thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; One (inbox tag1 unread)
-thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Two (inbox tag1 tag2 unread)
-thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Three (inbox tag3 unread)"
-
-test_done
+++ /dev/null
-#!/usr/bin/env bash
-
-test_description='"notmuch config"'
-. ./test-lib.sh
-
-test_begin_subtest "Get string value"
-test_expect_equal "$(notmuch config get user.name)" "Notmuch Test Suite"
-
-test_begin_subtest "Get list value"
-test_expect_equal "$(notmuch config get new.tags)" "\
-unread
-inbox"
-
-test_begin_subtest "Set string value"
-notmuch config set foo.string "this is a string value"
-test_expect_equal "$(notmuch config get foo.string)" "this is a string value"
-
-test_begin_subtest "Set string value again"
-notmuch config set foo.string "this is another string value"
-test_expect_equal "$(notmuch config get foo.string)" "this is another string value"
-
-test_begin_subtest "Set list value"
-notmuch config set foo.list this "is a" "list value"
-test_expect_equal "$(notmuch config get foo.list)" "\
-this
-is a
-list value"
-
-test_begin_subtest "Set list value again"
-notmuch config set foo.list this "is another" "list value"
-test_expect_equal "$(notmuch config get foo.list)" "\
-this
-is another
-list value"
-
-test_begin_subtest "Remove key"
-notmuch config set foo.remove baz
-notmuch config set foo.remove
-test_expect_equal "$(notmuch config get foo.remove)" ""
-
-test_begin_subtest "Remove non-existent key"
-notmuch config set foo.nonexistent
-test_expect_equal "$(notmuch config get foo.nonexistent)" ""
-
-test_begin_subtest "List all items"
-notmuch config set database.path "/canonical/path"
-output=$(notmuch config list)
-test_expect_equal "$output" "\
-database.path=/canonical/path
-user.name=Notmuch Test Suite
-user.primary_email=test_suite@notmuchmail.org
-user.other_email=test_suite_other@notmuchmail.org;test_suite@otherdomain.org
-new.tags=unread;inbox;
-new.ignore=
-search.exclude_tags=
-maildir.synchronize_flags=true
-foo.string=this is another string value
-foo.list=this;is another;list value;"
-
-test_begin_subtest "Top level --config=FILE option"
-cp "${NOTMUCH_CONFIG}" alt-config
-notmuch --config=alt-config config set user.name "Another Name"
-test_expect_equal "$(notmuch --config=alt-config config get user.name)" \
- "Another Name"
-
-test_begin_subtest "Top level --config=FILE option changed the right file"
-test_expect_equal "$(notmuch config get user.name)" \
- "Notmuch Test Suite"
-
-test_begin_subtest "Read config file through a symlink"
-ln -s alt-config alt-config-link
-test_expect_equal "$(notmuch --config=alt-config-link config get user.name)" \
- "Another Name"
-
-test_begin_subtest "Write config file through a symlink"
-notmuch --config=alt-config-link config set user.name "Link Name"
-test_expect_equal "$(notmuch --config=alt-config-link config get user.name)" \
- "Link Name"
-
-test_begin_subtest "Writing config file through symlink follows symlink"
-test_expect_equal "$(readlink alt-config-link)" "alt-config"
-
-test_done
+++ /dev/null
-#!/usr/bin/env bash
-test_description='"notmuch count" for messages and threads'
-. ./test-lib.sh
-
-add_email_corpus
-
-# Note: The 'wc -l' results below are wrapped in arithmetic evaluation
-# $((...)) to strip whitespace. This is for portability, as 'wc -l'
-# emits whitespace on some BSD variants.
-
-test_begin_subtest "message count is the default for notmuch count"
-test_expect_equal \
- "$((`notmuch search --output=messages '*' | wc -l`))" \
- "`notmuch count '*'`"
-
-test_begin_subtest "message count with --output=messages"
-test_expect_equal \
- "$((`notmuch search --output=messages '*' | wc -l`))" \
- "`notmuch count --output=messages '*'`"
-
-test_begin_subtest "thread count with --output=threads"
-test_expect_equal \
- "$((`notmuch search --output=threads '*' | wc -l`))" \
- "`notmuch count --output=threads '*'`"
-
-test_begin_subtest "thread count is the default for notmuch search"
-test_expect_equal \
- "$((`notmuch search '*' | wc -l`))" \
- "`notmuch count --output=threads '*'`"
-
-test_begin_subtest "files count"
-test_expect_equal \
- "$((`notmuch search --output=files '*' | wc -l`))" \
- "`notmuch count --output=files '*'`"
-
-test_begin_subtest "files count for a duplicate message-id"
-test_expect_equal \
- "2" \
- "`notmuch count --output=files id:20091117232137.GA7669@griffis1.net`"
-
-test_begin_subtest "count with no matching messages"
-test_expect_equal \
- "0" \
- "`notmuch count --output=messages from:cworth and not from:cworth`"
-
-test_begin_subtest "count with no matching threads"
-test_expect_equal \
- "0" \
- "`notmuch count --output=threads from:cworth and not from:cworth`"
-
-test_begin_subtest "message count is the default for batch count"
-notmuch count --batch >OUTPUT <<EOF
-
-from:cworth
-EOF
-notmuch count --output=messages >EXPECTED
-notmuch count --output=messages from:cworth >>EXPECTED
-test_expect_equal_file EXPECTED OUTPUT
-
-test_begin_subtest "batch message count"
-notmuch count --batch --output=messages >OUTPUT <<EOF
-from:cworth
-
-tag:inbox
-EOF
-notmuch count --output=messages from:cworth >EXPECTED
-notmuch count --output=messages >>EXPECTED
-notmuch count --output=messages tag:inbox >>EXPECTED
-test_expect_equal_file EXPECTED OUTPUT
-
-test_begin_subtest "batch thread count"
-notmuch count --batch --output=threads >OUTPUT <<EOF
-
-from:cworth
-from:cworth and not from:cworth
-foo
-EOF
-notmuch count --output=threads >EXPECTED
-notmuch count --output=threads from:cworth >>EXPECTED
-notmuch count --output=threads from:cworth and not from:cworth >>EXPECTED
-notmuch count --output=threads foo >>EXPECTED
-test_expect_equal_file EXPECTED OUTPUT
-
-test_begin_subtest "batch message count with input file"
-cat >INPUT <<EOF
-from:cworth
-
-tag:inbox
-EOF
-notmuch count --input=INPUT --output=messages >OUTPUT
-notmuch count --output=messages from:cworth >EXPECTED
-notmuch count --output=messages >>EXPECTED
-notmuch count --output=messages tag:inbox >>EXPECTED
-test_expect_equal_file EXPECTED OUTPUT
-
-
-test_done
+++ /dev/null
-#!/usr/bin/env bash
-
-# TODO:
-# - decryption/verification with signer key not available
-# - verification of signatures from expired/revoked keys
-
-test_description='PGP/MIME signature verification and decryption'
-. ./test-lib.sh
-
-add_gnupg_home ()
-{
- local output
- [ -d ${GNUPGHOME} ] && return
- mkdir -m 0700 "$GNUPGHOME"
- gpg --no-tty --import <$TEST_DIRECTORY/gnupg-secret-key.asc >"$GNUPGHOME"/import.log 2>&1
- test_debug "cat $GNUPGHOME/import.log"
- if (gpg --quick-random --version >/dev/null 2>&1) ; then
- echo quick-random >> "$GNUPGHOME"/gpg.conf
- elif (gpg --debug-quick-random --version >/dev/null 2>&1) ; then
- echo debug-quick-random >> "$GNUPGHOME"/gpg.conf
- fi
- echo no-emit-version >> "$GNUPGHOME"/gpg.conf
-}
-
-##################################################
-
-add_gnupg_home
-# get key fingerprint
-FINGERPRINT=$(gpg --no-tty --list-secret-keys --with-colons --fingerprint | grep '^fpr:' | cut -d: -f10)
-
-test_expect_success 'emacs delivery of signed message' \
-'emacs_fcc_message \
- "test signed message 001" \
- "This is a test signed message." \
- "(mml-secure-message-sign)"'
-
-test_begin_subtest "signature verification"
-output=$(notmuch show --format=json --verify subject:"test signed message 001" \
- | notmuch_json_show_sanitize \
- | sed -e 's|"created": [1234567890]*|"created": 946728000|')
-expected='[[[{"id": "XXXXX",
- "match": true,
- "excluded": false,
- "filename": "YYYYY",
- "timestamp": 946728000,
- "date_relative": "2000-01-01",
- "tags": ["inbox","signed"],
- "headers": {"Subject": "test signed message 001",
- "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
- "To": "test_suite@notmuchmail.org",
- "Date": "Sat, 01 Jan 2000 12:00:00 +0000"},
- "body": [{"id": 1,
- "sigstatus": [{"status": "good",
- "fingerprint": "'$FINGERPRINT'",
- "created": 946728000}],
- "content-type": "multipart/signed",
- "content": [{"id": 2,
- "content-type": "text/plain",
- "content": "This is a test signed message.\n"},
- {"id": 3,
- "content-type": "application/pgp-signature",
- "content-length": 280}]}]},
- []]]]'
-test_expect_equal_json \
- "$output" \
- "$expected"
-
-test_begin_subtest "signature verification with full owner trust"
-# give the key full owner trust
-echo "${FINGERPRINT}:6:" | gpg --no-tty --import-ownertrust >>"$GNUPGHOME"/trust.log 2>&1
-gpg --no-tty --check-trustdb >>"$GNUPGHOME"/trust.log 2>&1
-output=$(notmuch show --format=json --verify subject:"test signed message 001" \
- | notmuch_json_show_sanitize \
- | sed -e 's|"created": [1234567890]*|"created": 946728000|')
-expected='[[[{"id": "XXXXX",
- "match": true,
- "excluded": false,
- "filename": "YYYYY",
- "timestamp": 946728000,
- "date_relative": "2000-01-01",
- "tags": ["inbox","signed"],
- "headers": {"Subject": "test signed message 001",
- "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
- "To": "test_suite@notmuchmail.org",
- "Date": "Sat, 01 Jan 2000 12:00:00 +0000"},
- "body": [{"id": 1,
- "sigstatus": [{"status": "good",
- "fingerprint": "'$FINGERPRINT'",
- "created": 946728000,
- "userid": " Notmuch Test Suite <test_suite@notmuchmail.org> (INSECURE!)"}],
- "content-type": "multipart/signed",
- "content": [{"id": 2,
- "content-type": "text/plain",
- "content": "This is a test signed message.\n"},
- {"id": 3,
- "content-type": "application/pgp-signature",
- "content-length": 280}]}]},
- []]]]'
-test_expect_equal_json \
- "$output" \
- "$expected"
-
-test_begin_subtest "signature verification with signer key unavailable"
-# move the gnupghome temporarily out of the way
-mv "${GNUPGHOME}"{,.bak}
-output=$(notmuch show --format=json --verify subject:"test signed message 001" \
- | notmuch_json_show_sanitize \
- | sed -e 's|"created": [1234567890]*|"created": 946728000|')
-expected='[[[{"id": "XXXXX",
- "match": true,
- "excluded": false,
- "filename": "YYYYY",
- "timestamp": 946728000,
- "date_relative": "2000-01-01",
- "tags": ["inbox","signed"],
- "headers": {"Subject": "test signed message 001",
- "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
- "To": "test_suite@notmuchmail.org",
- "Date": "Sat, 01 Jan 2000 12:00:00 +0000"},
- "body": [{"id": 1,
- "sigstatus": [{"status": "error",
- "keyid": "'$(echo $FINGERPRINT | cut -c 25-)'",
- "errors": 2}],
- "content-type": "multipart/signed",
- "content": [{"id": 2,
- "content-type": "text/plain",
- "content": "This is a test signed message.\n"},
- {"id": 3,
- "content-type": "application/pgp-signature",
- "content-length": 280}]}]},
- []]]]'
-test_expect_equal_json \
- "$output" \
- "$expected"
-mv "${GNUPGHOME}"{.bak,}
-
-# create a test encrypted message with attachment
-cat <<EOF >TESTATTACHMENT
-This is a test file.
-EOF
-test_expect_success 'emacs delivery of encrypted message with attachment' \
-'emacs_fcc_message \
- "test encrypted message 001" \
- "This is a test encrypted message.\n" \
- "(mml-attach-file \"TESTATTACHMENT\") (mml-secure-message-encrypt)"'
-
-test_begin_subtest "decryption, --format=text"
-output=$(notmuch show --format=text --decrypt subject:"test encrypted message 001" \
- | notmuch_show_sanitize_all \
- | sed -e 's|"created": [1234567890]*|"created": 946728000|')
-expected='\fmessage{ id:XXXXX depth:0 match:1 excluded:0 filename:XXXXX
-\fheader{
-Notmuch Test Suite <test_suite@notmuchmail.org> (2000-01-01) (encrypted inbox)
-Subject: test encrypted message 001
-From: Notmuch Test Suite <test_suite@notmuchmail.org>
-To: test_suite@notmuchmail.org
-Date: Sat, 01 Jan 2000 12:00:00 +0000
-\fheader}
-\fbody{
-\fpart{ ID: 1, Content-type: multipart/encrypted
-\fpart{ ID: 2, Content-type: application/pgp-encrypted
-Non-text part: application/pgp-encrypted
-\fpart}
-\fpart{ ID: 3, Content-type: multipart/mixed
-\fpart{ ID: 4, Content-type: text/plain
-This is a test encrypted message.
-\fpart}
-\fattachment{ ID: 5, Filename: TESTATTACHMENT, Content-type: application/octet-stream
-Non-text part: application/octet-stream
-\fattachment}
-\fpart}
-\fpart}
-\fbody}
-\fmessage}'
-test_expect_equal \
- "$output" \
- "$expected"
-
-test_begin_subtest "decryption, --format=json"
-output=$(notmuch show --format=json --decrypt subject:"test encrypted message 001" \
- | notmuch_json_show_sanitize \
- | sed -e 's|"created": [1234567890]*|"created": 946728000|')
-expected='[[[{"id": "XXXXX",
- "match": true,
- "excluded": false,
- "filename": "YYYYY",
- "timestamp": 946728000,
- "date_relative": "2000-01-01",
- "tags": ["encrypted","inbox"],
- "headers": {"Subject": "test encrypted message 001",
- "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
- "To": "test_suite@notmuchmail.org",
- "Date": "Sat, 01 Jan 2000 12:00:00 +0000"},
- "body": [{"id": 1,
- "encstatus": [{"status": "good"}],
- "sigstatus": [],
- "content-type": "multipart/encrypted",
- "content": [{"id": 2,
- "content-type": "application/pgp-encrypted",
- "content-length": 11},
- {"id": 3,
- "content-type": "multipart/mixed",
- "content": [{"id": 4,
- "content-type": "text/plain",
- "content": "This is a test encrypted message.\n"},
- {"id": 5,
- "content-type": "application/octet-stream",
- "content-length": 28,
- "content-transfer-encoding": "base64",
- "filename": "TESTATTACHMENT"}]}]}]},
- []]]]'
-test_expect_equal_json \
- "$output" \
- "$expected"
-
-test_begin_subtest "decryption, --format=json, --part=4"
-output=$(notmuch show --format=json --part=4 --decrypt subject:"test encrypted message 001" \
- | notmuch_json_show_sanitize \
- | sed -e 's|"created": [1234567890]*|"created": 946728000|')
-expected='{"id": 4,
- "content-type": "text/plain",
- "content": "This is a test encrypted message.\n"}'
-test_expect_equal_json \
- "$output" \
- "$expected"
-
-test_begin_subtest "decrypt attachment (--part=5 --format=raw)"
-notmuch show \
- --format=raw \
- --part=5 \
- --decrypt \
- subject:"test encrypted message 001" >OUTPUT
-test_expect_equal_file OUTPUT TESTATTACHMENT
-
-test_begin_subtest "decryption failure with missing key"
-mv "${GNUPGHOME}"{,.bak}
-# The length of the encrypted attachment varies so must be normalized.
-output=$(notmuch show --format=json --decrypt subject:"test encrypted message 001" \
- | notmuch_json_show_sanitize \
- | sed -e 's|"created": [1234567890]*|"created": 946728000|' \
- | sed -e 's|"content-length": 6[1234567890]*|"content-length": 652|')
-expected='[[[{"id": "XXXXX",
- "match": true,
- "excluded": false,
- "filename": "YYYYY",
- "timestamp": 946728000,
- "date_relative": "2000-01-01",
- "tags": ["encrypted","inbox"],
- "headers": {"Subject": "test encrypted message 001",
- "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
- "To": "test_suite@notmuchmail.org",
- "Date": "Sat, 01 Jan 2000 12:00:00 +0000"},
- "body": [{"id": 1,
- "encstatus": [{"status": "bad"}],
- "content-type": "multipart/encrypted",
- "content": [{"id": 2,
- "content-type": "application/pgp-encrypted",
- "content-length": 11},
- {"id": 3,
- "content-type": "application/octet-stream",
- "content-length": 652}]}]},
- []]]]'
-test_expect_equal_json \
- "$output" \
- "$expected"
-mv "${GNUPGHOME}"{.bak,}
-
-test_expect_success 'emacs delivery of encrypted + signed message' \
-'emacs_fcc_message \
- "test encrypted message 002" \
- "This is another test encrypted message.\n" \
- "(mml-secure-message-sign-encrypt)"'
-
-test_begin_subtest "decryption + signature verification"
-output=$(notmuch show --format=json --decrypt subject:"test encrypted message 002" \
- | notmuch_json_show_sanitize \
- | sed -e 's|"created": [1234567890]*|"created": 946728000|')
-expected='[[[{"id": "XXXXX",
- "match": true,
- "excluded": false,
- "filename": "YYYYY",
- "timestamp": 946728000,
- "date_relative": "2000-01-01",
- "tags": ["encrypted","inbox"],
- "headers": {"Subject": "test encrypted message 002",
- "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
- "To": "test_suite@notmuchmail.org",
- "Date": "Sat, 01 Jan 2000 12:00:00 +0000"},
- "body": [{"id": 1,
- "encstatus": [{"status": "good"}],
- "sigstatus": [{"status": "good",
- "fingerprint": "'$FINGERPRINT'",
- "created": 946728000,
- "userid": " Notmuch Test Suite <test_suite@notmuchmail.org> (INSECURE!)"}],
- "content-type": "multipart/encrypted",
- "content": [{"id": 2,
- "content-type": "application/pgp-encrypted",
- "content-length": 11},
- {"id": 3,
- "content-type": "text/plain",
- "content": "This is another test encrypted message.\n"}]}]},
- []]]]'
-test_expect_equal_json \
- "$output" \
- "$expected"
-
-test_begin_subtest "reply to encrypted message"
-output=$(notmuch reply --decrypt subject:"test encrypted message 002" \
- | grep -v -e '^In-Reply-To:' -e '^References:')
-expected='From: Notmuch Test Suite <test_suite@notmuchmail.org>
-Subject: Re: test encrypted message 002
-
-On 01 Jan 2000 12:00:00 -0000, Notmuch Test Suite <test_suite@notmuchmail.org> wrote:
-> This is another test encrypted message.'
-test_expect_equal \
- "$output" \
- "$expected"
-
-test_begin_subtest "signature verification with revoked key"
-# generate revocation certificate and load it to revoke key
-echo "y
-1
-Notmuch Test Suite key revocation (automated) $(date '+%F_%T%z')
-
-y
-
-" \
- | gpg --no-tty --quiet --command-fd 0 --armor --gen-revoke "0x${FINGERPRINT}!" 2>/dev/null \
- | gpg --no-tty --quiet --import
-output=$(notmuch show --format=json --verify subject:"test signed message 001" \
- | notmuch_json_show_sanitize \
- | sed -e 's|"created": [1234567890]*|"created": 946728000|')
-expected='[[[{"id": "XXXXX",
- "match": true,
- "excluded": false,
- "filename": "YYYYY",
- "timestamp": 946728000,
- "date_relative": "2000-01-01",
- "tags": ["inbox","signed"],
- "headers": {"Subject": "test signed message 001",
- "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
- "To": "test_suite@notmuchmail.org",
- "Date": "Sat, 01 Jan 2000 12:00:00 +0000"},
- "body": [{"id": 1,
- "sigstatus": [{"status": "error",
- "keyid": "6D92612D94E46381",
- "errors": 8}],
- "content-type": "multipart/signed",
- "content": [{"id": 2,
- "content-type": "text/plain",
- "content": "This is a test signed message.\n"},
- {"id": 3,
- "content-type": "application/pgp-signature",
- "content-length": 280}]}]},
- []]]]'
-test_expect_equal_json \
- "$output" \
- "$expected"
-
-test_done
+++ /dev/null
-#!/usr/bin/env bash
-test_description="\"notmuch dump\" and \"notmuch restore\""
-. ./test-lib.sh
-
-add_email_corpus
-
-test_expect_success 'Dumping all tags' \
- 'generate_message &&
- notmuch new &&
- notmuch dump > dump.expected'
-
-# The use of from:cworth is rather arbitrary: it matches some of the
-# email corpus' messages, but not all of them.
-
-test_expect_success 'Dumping all tags II' \
- 'notmuch tag +ABC +DEF -- from:cworth &&
- notmuch dump > dump-ABC_DEF.expected &&
- ! cmp dump.expected dump-ABC_DEF.expected'
-
-test_expect_success 'Clearing all tags' \
- 'sed -e "s/(\([^(]*\))$/()/" < dump.expected > clear.expected &&
- notmuch restore --input=clear.expected &&
- notmuch dump > clear.actual &&
- test_cmp clear.expected clear.actual'
-
-test_expect_success 'Accumulate original tags' \
- 'notmuch tag +ABC +DEF -- from:cworth &&
- notmuch restore --accumulate < dump.expected &&
- notmuch dump > dump.actual &&
- test_cmp dump-ABC_DEF.expected dump.actual'
-
-test_expect_success 'Restoring original tags' \
- 'notmuch restore --input=dump.expected &&
- notmuch dump > dump.actual &&
- test_cmp dump.expected dump.actual'
-
-test_expect_success 'Restore with nothing to do' \
- 'notmuch restore < dump.expected &&
- notmuch dump > dump.actual &&
- test_cmp dump.expected dump.actual'
-
-test_expect_success 'Accumulate with existing tags' \
- 'notmuch restore --accumulate --input=dump.expected &&
- notmuch dump > dump.actual &&
- test_cmp dump.expected dump.actual'
-
-test_expect_success 'Accumulate with no tags' \
- 'notmuch restore --accumulate < clear.expected &&
- notmuch dump > dump.actual &&
- test_cmp dump.expected dump.actual'
-
-test_expect_success 'Accumulate with new tags' \
- 'notmuch restore --input=dump.expected &&
- notmuch restore --accumulate --input=dump-ABC_DEF.expected &&
- notmuch dump > OUTPUT.$test_count &&
- notmuch restore --input=dump.expected &&
- test_cmp dump-ABC_DEF.expected OUTPUT.$test_count'
-
-# notmuch restore currently only considers the first argument.
-test_expect_success 'Invalid restore invocation' \
- 'test_must_fail notmuch restore --input=dump.expected another_one'
-
-test_begin_subtest "dump --output=outfile"
-notmuch dump --output=dump-outfile.actual
-test_expect_equal_file dump.expected dump-outfile.actual
-
-test_begin_subtest "dump --output=outfile --"
-notmuch dump --output=dump-1-arg-dash.actual --
-test_expect_equal_file dump.expected dump-1-arg-dash.actual
-
-# Note, we assume all messages from cworth have a message-id
-# containing cworth.org
-
-grep 'cworth[.]org' dump.expected > dump-cworth.expected
-
-test_begin_subtest "dump -- from:cworth"
-notmuch dump -- from:cworth > dump-dash-cworth.actual
-test_expect_equal_file dump-cworth.expected dump-dash-cworth.actual
-
-test_begin_subtest "dump --output=outfile from:cworth"
-notmuch dump --output=dump-outfile-cworth.actual from:cworth
-test_expect_equal_file dump-cworth.expected dump-outfile-cworth.actual
-
-test_begin_subtest "dump --output=outfile -- from:cworth"
-notmuch dump --output=dump-outfile-dash-inbox.actual -- from:cworth
-test_expect_equal_file dump-cworth.expected dump-outfile-dash-inbox.actual
-
-test_begin_subtest "Check for a safe set of message-ids"
-notmuch search --output=messages from:cworth | sed s/^id:// > EXPECTED
-notmuch search --output=messages from:cworth | sed s/^id:// |\
- $TEST_DIRECTORY/hex-xcode --direction=encode > OUTPUT
-test_expect_equal_file OUTPUT EXPECTED
-
-test_begin_subtest "format=batch-tag, dump sanity check."
-notmuch dump --format=sup from:cworth | cut -f1 -d' ' | \
- sort > EXPECTED.$test_count
-notmuch dump --format=batch-tag from:cworth | sed 's/^.*-- id://' | \
- sort > OUTPUT.$test_count
-test_expect_equal_file EXPECTED.$test_count OUTPUT.$test_count
-
-test_begin_subtest "format=batch-tag, # round-trip"
-notmuch dump --format=sup | sort > EXPECTED.$test_count
-notmuch dump --format=batch-tag | notmuch restore --format=batch-tag
-notmuch dump --format=sup | sort > OUTPUT.$test_count
-test_expect_equal_file EXPECTED.$test_count OUTPUT.$test_count
-
-test_begin_subtest "format=batch-tag, # blank lines and comments"
-notmuch dump --format=batch-tag| sort > EXPECTED.$test_count
-notmuch restore <<EOF
-# this line is a comment; the next has only white space
-
-
-# the previous line is empty
-EOF
-notmuch dump --format=batch-tag | sort > OUTPUT.$test_count
-test_expect_equal_file EXPECTED.$test_count OUTPUT.$test_count
-
-test_begin_subtest "format=batch-tag, # reverse-round-trip empty tag"
-cat <<EOF >EXPECTED.$test_count
-+ -- id:20091117232137.GA7669@griffis1.net
-EOF
-notmuch restore --format=batch-tag < EXPECTED.$test_count
-notmuch dump --format=batch-tag id:20091117232137.GA7669@griffis1.net > OUTPUT.$test_count
-test_expect_equal_file EXPECTED.$test_count OUTPUT.$test_count
-
-tag1='comic_swear=$&^%$^%\\//-+$^%$'
-enc1=$($TEST_DIRECTORY/hex-xcode --direction=encode "$tag1")
-
-tag2=$(printf 'this\n tag\t has\n spaces')
-enc2=$($TEST_DIRECTORY/hex-xcode --direction=encode "$tag2")
-
-enc3='%c3%91%c3%a5%c3%b0%c3%a3%c3%a5%c3%a9-%c3%8f%c3%8a'
-tag3=$($TEST_DIRECTORY/hex-xcode --direction=decode $enc3)
-
-notmuch dump --format=batch-tag > BACKUP
-
-notmuch tag +"$tag1" +"$tag2" +"$tag3" -inbox -unread "*"
-
-# initial segment of file used for several tests below.
-cat <<EOF > comments-and-blanks
-# this is a comment
-
-# next line has leading whitespace
-
-
-EOF
-
-test_begin_subtest 'restoring empty file is not an error'
-notmuch restore < /dev/null 2>OUTPUT.$test_count
-cp /dev/null EXPECTED
-test_expect_equal_file EXPECTED OUTPUT.$test_count
-
-test_begin_subtest 'file of comments and blank lines is not an error'
-notmuch restore --input=comments-and-blanks
-ret_val=$?
-test_expect_equal "$ret_val" "0"
-
-cp comments-and-blanks leading-comments-blanks-batch-tag
-echo "+some_tag -- id:yun1vjwegii.fsf@aiko.keithp.com" \
- >> leading-comments-blanks-batch-tag
-
-test_begin_subtest 'detect format=batch-tag with leading comments and blanks'
-notmuch restore --input=leading-comments-blanks-batch-tag
-notmuch search --output=tags id:yun1vjwegii.fsf@aiko.keithp.com > OUTPUT.$test_count
-echo "some_tag" > EXPECTED
-test_expect_equal_file EXPECTED OUTPUT.$test_count
-
-cp comments-and-blanks leading-comments-blanks-sup
-echo "yun1vjwegii.fsf@aiko.keithp.com (another_tag)" \
- >> leading-comments-blanks-sup
-
-test_begin_subtest 'detect format=sup with leading comments and blanks'
-notmuch restore --input=leading-comments-blanks-sup
-notmuch search --output=tags id:yun1vjwegii.fsf@aiko.keithp.com > OUTPUT.$test_count
-echo "another_tag" > EXPECTED
-test_expect_equal_file EXPECTED OUTPUT.$test_count
-
-test_begin_subtest 'format=batch-tag, round trip with strange tags'
-notmuch dump --format=batch-tag > EXPECTED.$test_count
-notmuch dump --format=batch-tag | notmuch restore --format=batch-tag
-notmuch dump --format=batch-tag > OUTPUT.$test_count
-test_expect_equal_file EXPECTED.$test_count OUTPUT.$test_count
-
-test_begin_subtest 'format=batch-tag, checking encoded output'
-notmuch dump --format=batch-tag -- from:cworth |\
- awk "{ print \"+$enc1 +$enc2 +$enc3 -- \" \$5 }" > EXPECTED.$test_count
-notmuch dump --format=batch-tag -- from:cworth > OUTPUT.$test_count
-test_expect_equal_file EXPECTED.$test_count OUTPUT.$test_count
-
-test_begin_subtest 'restoring sane tags'
-notmuch restore --format=batch-tag < BACKUP
-notmuch dump --format=batch-tag > OUTPUT.$test_count
-test_expect_equal_file BACKUP OUTPUT.$test_count
-
-test_begin_subtest 'format=batch-tag, restore=auto'
-notmuch dump --format=batch-tag > EXPECTED.$test_count
-notmuch tag -inbox -unread "*"
-notmuch restore --format=auto < EXPECTED.$test_count
-notmuch dump --format=batch-tag > OUTPUT.$test_count
-test_expect_equal_file EXPECTED.$test_count OUTPUT.$test_count
-
-test_begin_subtest 'format=sup, restore=auto'
-notmuch dump --format=sup > EXPECTED.$test_count
-notmuch tag -inbox -unread "*"
-notmuch restore --format=auto < EXPECTED.$test_count
-notmuch dump --format=sup > OUTPUT.$test_count
-test_expect_equal_file EXPECTED.$test_count OUTPUT.$test_count
-
-test_begin_subtest 'format=batch-tag, restore=default'
-notmuch dump --format=batch-tag > EXPECTED.$test_count
-notmuch tag -inbox -unread "*"
-notmuch restore < EXPECTED.$test_count
-notmuch dump --format=batch-tag > OUTPUT.$test_count
-test_expect_equal_file EXPECTED.$test_count OUTPUT.$test_count
-
-test_begin_subtest 'format=sup, restore=default'
-notmuch dump --format=sup > EXPECTED.$test_count
-notmuch tag -inbox -unread "*"
-notmuch restore < EXPECTED.$test_count
-notmuch dump --format=sup > OUTPUT.$test_count
-test_expect_equal_file EXPECTED.$test_count OUTPUT.$test_count
-
-test_begin_subtest 'restore: checking error messages'
-notmuch restore <<EOF 2>OUTPUT
-# the next line has a space
-
-a
-+0
-+a +b
-# trailing whitespace
-+a +b
-+c +d --
-# this is a harmless comment, do not yell about it.
-
-# the previous line was blank; also no yelling please
-+%zz -- id:whatever
-+e +f id:"
-+e +f tag:abc
-# the next non-comment line should report an an empty tag error for
-# batch tagging, but not for restore
-+ +e -- id:20091117232137.GA7669@griffis1.net
-# valid id, but warning about missing message
-+e id:missing_message_id
-# exercise parser
-+e -- id:some)stuff
-+e -- id:some stuff
-+e -- id:some"stuff
-+e -- id:"a_message_id_with""_a_quote"
-+e -- id:"a message id with spaces"
-+e -- id:an_id_with_leading_and_trailing_ws \
-
-EOF
-
-cat <<EOF > EXPECTED
-Warning: cannot parse query: a (skipping)
-Warning: no query string [+0]
-Warning: no query string [+a +b]
-Warning: missing query string [+a +b ]
-Warning: no query string after -- [+c +d --]
-Warning: hex decoding of tag %zz failed [+%zz -- id:whatever]
-Warning: cannot parse query: id:" (skipping)
-Warning: not an id query: tag:abc (skipping)
-Warning: cannot apply tags to missing message: missing_message_id
-Warning: cannot parse query: id:some)stuff (skipping)
-Warning: cannot parse query: id:some stuff (skipping)
-Warning: cannot apply tags to missing message: some"stuff
-Warning: cannot apply tags to missing message: a_message_id_with"_a_quote
-Warning: cannot apply tags to missing message: a message id with spaces
-Warning: cannot apply tags to missing message: an_id_with_leading_and_trailing_ws
-EOF
-
-test_expect_equal_file EXPECTED OUTPUT
-
-test_begin_subtest 'roundtripping random message-ids and tags'
-
- ${TEST_DIRECTORY}/random-corpus --config-path=${NOTMUCH_CONFIG} \
- --num-messages=100
-
- notmuch dump --format=batch-tag| \
- sort > EXPECTED.$test_count
-
- notmuch tag +this_tag_is_very_unlikely_to_be_random '*'
-
- notmuch restore --format=batch-tag < EXPECTED.$test_count
-
- notmuch dump --format=batch-tag| \
- sort > OUTPUT.$test_count
-
-test_expect_equal_file EXPECTED.$test_count OUTPUT.$test_count
-
-test_done
-
-# Note the database is "poisoned" for sup format at this point.
+++ /dev/null
-#!/usr/bin/env bash
-
-test_description="emacs interface"
-. ./test-lib.sh
-
-EXPECTED=$TEST_DIRECTORY/emacs.expected-output
-
-add_email_corpus
-
-test_begin_subtest "Basic notmuch-hello view in emacs"
-test_emacs '(notmuch-hello)
- (test-output)'
-test_expect_equal_file OUTPUT $EXPECTED/notmuch-hello
-
-test_begin_subtest "Saved search with 0 results"
-test_emacs '(let ((notmuch-show-empty-saved-searches t)
- (notmuch-saved-searches
- '\''(("inbox" . "tag:inbox")
- ("unread" . "tag:unread")
- ("empty" . "tag:doesnotexist"))))
- (notmuch-hello)
- (test-output))'
-test_expect_equal_file OUTPUT $EXPECTED/notmuch-hello-with-empty
-
-test_begin_subtest "No saved searches displayed (all with 0 results)"
-test_emacs '(let ((notmuch-saved-searches
- '\''(("empty" . "tag:doesnotexist"))))
- (notmuch-hello)
- (test-output))'
-test_expect_equal_file OUTPUT $EXPECTED/notmuch-hello-no-saved-searches
-
-test_begin_subtest "Basic notmuch-search view in emacs"
-test_emacs '(notmuch-search "tag:inbox")
- (notmuch-test-wait)
- (test-output)'
-test_expect_equal_file OUTPUT $EXPECTED/notmuch-search-tag-inbox
-
-test_begin_subtest "Incremental parsing of search results"
-test_emacs "(ad-enable-advice 'notmuch-search-process-filter 'around 'pessimal)
- (ad-activate 'notmuch-search-process-filter)
- (notmuch-search \"tag:inbox\")
- (notmuch-test-wait)
- (ad-disable-advice 'notmuch-search-process-filter 'around 'pessimal)
- (ad-activate 'notmuch-search-process-filter)
- (test-output)"
-test_expect_equal_file OUTPUT $EXPECTED/notmuch-search-tag-inbox
-
-test_begin_subtest "Navigation of notmuch-hello to search results"
-test_emacs '(notmuch-hello)
- (goto-char (point-min))
- (re-search-forward "inbox")
- (widget-button-press (1- (point)))
- (notmuch-test-wait)
- (test-output)'
-test_expect_equal_file OUTPUT $EXPECTED/notmuch-hello-view-inbox
-
-test_begin_subtest "Basic notmuch-show view in emacs"
-maildir_storage_thread=$(notmuch search --output=threads id:20091117190054.GU3165@dottiness.seas.harvard.edu)
-test_emacs "(notmuch-show \"$maildir_storage_thread\")
- (test-output)"
-test_expect_equal_file OUTPUT $EXPECTED/notmuch-show-thread-maildir-storage
-
-test_begin_subtest "Basic notmuch-show view in emacs default indentation"
-maildir_storage_thread=$(notmuch search --output=threads id:20091117190054.GU3165@dottiness.seas.harvard.edu)
-test_emacs "(let ((notmuch-show-indent-messages-width 1))
- (notmuch-show \"$maildir_storage_thread\")
- (test-output))"
-test_expect_equal_file OUTPUT $EXPECTED/notmuch-show-thread-maildir-storage
-
-test_begin_subtest "Basic notmuch-show view in emacs without indentation"
-maildir_storage_thread=$(notmuch search --output=threads id:20091117190054.GU3165@dottiness.seas.harvard.edu)
-test_emacs "(let ((notmuch-show-indent-messages-width 0))
- (notmuch-show \"$maildir_storage_thread\")
- (test-output))"
-test_expect_equal_file OUTPUT $EXPECTED/notmuch-show-thread-maildir-storage-without-indentation
-
-test_begin_subtest "Basic notmuch-show view in emacs with fourfold indentation"
-maildir_storage_thread=$(notmuch search --output=threads id:20091117190054.GU3165@dottiness.seas.harvard.edu)
-test_emacs "(let ((notmuch-show-indent-messages-width 4))
- (notmuch-show \"$maildir_storage_thread\")
- (test-output))"
-test_expect_equal_file OUTPUT $EXPECTED/notmuch-show-thread-maildir-storage-with-fourfold-indentation
-
-test_begin_subtest "notmuch-show for message with invalid From"
-add_message "[subject]=\"message-with-invalid-from\"" \
- "[from]=\"\\\"Invalid \\\" From\\\" <test_suite@notmuchmail.org>\""
-thread=$(notmuch search --output=threads subject:message-with-invalid-from)
-test_emacs "(notmuch-show \"$thread\")
- (test-output \"OUTPUT.raw\")"
-cat <<EOF >EXPECTED
-"Invalid " (2001-01-05) (inbox)
-Subject: message-with-invalid-from
-To: Notmuch Test Suite <test_suite@notmuchmail.org>
-Date: GENERATED_DATE
-
-This is just a test message (#1)
-EOF
-notmuch_date_sanitize < OUTPUT.raw > OUTPUT
-test_expect_equal_file OUTPUT EXPECTED
-
-test_begin_subtest "Navigation of notmuch-search to thread view"
-test_emacs '(notmuch-search "tag:inbox")
- (notmuch-test-wait)
- (goto-char (point-min))
- (re-search-forward "Working with Maildir")
- (notmuch-search-show-thread)
- (notmuch-test-wait)
- (test-output)'
-test_expect_equal_file OUTPUT $EXPECTED/notmuch-show-thread-maildir-storage
-
-test_begin_subtest "Add tag from search view"
-os_x_darwin_thread=$(notmuch search --output=threads id:ddd65cda0911171950o4eea4389v86de9525e46052d3@mail.gmail.com)
-test_emacs "(notmuch-search \"$os_x_darwin_thread\")
- (notmuch-test-wait)
- (execute-kbd-macro \"+tag-from-search-view\")"
-output=$(notmuch search $os_x_darwin_thread | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2009-11-18 [4/4] Jjgod Jiang, Alexander Botero-Lowry; [notmuch] Mac OS X/Darwin compatibility issues (inbox tag-from-search-view unread)"
-
-test_begin_subtest "Remove tag from search view"
-test_emacs "(notmuch-search \"$os_x_darwin_thread\")
- (notmuch-test-wait)
- (execute-kbd-macro \"-tag-from-search-view\")"
-output=$(notmuch search $os_x_darwin_thread | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2009-11-18 [4/4] Jjgod Jiang, Alexander Botero-Lowry; [notmuch] Mac OS X/Darwin compatibility issues (inbox unread)"
-
-test_begin_subtest "Add tag (large query)"
-# We use a long query to force us into batch mode and use a funny tag
-# that requires escaping for batch tagging.
-test_emacs "(notmuch-tag (concat \"$os_x_darwin_thread\" \" or \" (make-string notmuch-tag-argument-limit ?x)) (list \"+tag-from-%-large-query\"))"
-output=$(notmuch search $os_x_darwin_thread | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2009-11-18 [4/4] Jjgod Jiang, Alexander Botero-Lowry; [notmuch] Mac OS X/Darwin compatibility issues (inbox tag-from-%-large-query unread)"
-notmuch tag -tag-from-%-large-query $os_x_darwin_thread
-
-test_begin_subtest "notmuch-show: add single tag to single message"
-test_emacs "(notmuch-show \"$os_x_darwin_thread\")
- (execute-kbd-macro \"+tag-from-show-view\")"
-output=$(notmuch search $os_x_darwin_thread | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2009-11-18 [4/4] Jjgod Jiang, Alexander Botero-Lowry; [notmuch] Mac OS X/Darwin compatibility issues (inbox tag-from-show-view unread)"
-
-test_begin_subtest "notmuch-show: remove single tag from single message"
-test_emacs "(notmuch-show \"$os_x_darwin_thread\")
- (execute-kbd-macro \"-tag-from-show-view\")"
-output=$(notmuch search $os_x_darwin_thread | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2009-11-18 [4/4] Jjgod Jiang, Alexander Botero-Lowry; [notmuch] Mac OS X/Darwin compatibility issues (inbox unread)"
-
-test_begin_subtest "notmuch-show: add multiple tags to single message"
-test_emacs "(notmuch-show \"$os_x_darwin_thread\")
- (execute-kbd-macro \"+tag1-from-show-view +tag2-from-show-view\")"
-output=$(notmuch search $os_x_darwin_thread | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2009-11-18 [4/4] Jjgod Jiang, Alexander Botero-Lowry; [notmuch] Mac OS X/Darwin compatibility issues (inbox tag1-from-show-view tag2-from-show-view unread)"
-
-test_begin_subtest "notmuch-show: remove multiple tags from single message"
-test_emacs "(notmuch-show \"$os_x_darwin_thread\")
- (execute-kbd-macro \"-tag1-from-show-view -tag2-from-show-view\")"
-output=$(notmuch search $os_x_darwin_thread | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2009-11-18 [4/4] Jjgod Jiang, Alexander Botero-Lowry; [notmuch] Mac OS X/Darwin compatibility issues (inbox unread)"
-
-test_begin_subtest "Message with .. in Message-Id:"
-add_message [id]=123..456@example '[subject]="Message with .. in Message-Id"'
-test_emacs '(notmuch-search "id:\"123..456@example\"")
- (notmuch-test-wait)
- (execute-kbd-macro "+search-add")
- (execute-kbd-macro "+search-remove")
- (execute-kbd-macro "-search-remove")
- (notmuch-show "id:\"123..456@example\"")
- (notmuch-test-wait)
- (execute-kbd-macro "+show-add")
- (execute-kbd-macro "+show-remove")
- (execute-kbd-macro "-show-remove")'
-output=$(notmuch search 'id:"123..456@example"' | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Message with .. in Message-Id (inbox search-add show-add)"
-
-test_begin_subtest "Message with quote in Message-Id:"
-add_message '[id]="\"quote\"@example"' '[subject]="Message with quote in Message-Id"'
-test_emacs '(notmuch-search "subject:\"Message with quote\"")
- (notmuch-test-wait)
- (execute-kbd-macro "+search-add")
- (notmuch-search-show-thread)
- (notmuch-test-wait)
- (execute-kbd-macro "+show-add")'
-output=$(notmuch search 'id:"""quote""@example"' | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Message with quote in Message-Id (inbox search-add show-add)"
-
-test_begin_subtest "Sending a message via (fake) SMTP"
-emacs_deliver_message \
- 'Testing message sent via SMTP' \
- 'This is a test that messages are sent via SMTP' \
- '(message-goto-to)
- (kill-whole-line)
- (insert "To: user@example.com\n")'
-sed \
- -e s',^User-Agent: Notmuch/.* Emacs/.*,User-Agent: Notmuch/XXX Emacs/XXX,' \
- -e s',^Message-ID: <.*>$,Message-ID: <XXX>,' \
- -e s',^\(Content-Type: text/plain\); charset=us-ascii$,\1,' < sent_message >OUTPUT
-cat <<EOF >EXPECTED
-From: Notmuch Test Suite <test_suite@notmuchmail.org>
-To: user@example.com
-Subject: Testing message sent via SMTP
-Date: 01 Jan 2000 12:00:00 -0000
-User-Agent: Notmuch/XXX Emacs/XXX
-Message-ID: <XXX>
-MIME-Version: 1.0
-Content-Type: text/plain
-
-This is a test that messages are sent via SMTP
-EOF
-test_expect_equal_file OUTPUT EXPECTED
-
-test_begin_subtest "Verify that sent messages are saved/searchable (via FCC)"
-notmuch new > /dev/null
-output=$(notmuch search 'subject:"testing message sent via SMTP"' | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; Testing message sent via SMTP (inbox)"
-
-test_begin_subtest "notmuch-fcc-dirs set to nil"
-test_emacs "(let ((notmuch-fcc-dirs nil))
- (notmuch-mua-mail)
- (test-output))"
-cat <<EOF >EXPECTED
-From: Notmuch Test Suite <test_suite@notmuchmail.org>
-To:
-Subject:
---text follows this line--
-EOF
-test_expect_equal_file OUTPUT EXPECTED
-
-# Make another FCC maildir specific for the next test
-mkdir -p mail/sent-string/cur
-mkdir -p mail/sent-string/new
-mkdir -p mail/sent-string/tmp
-
-test_begin_subtest "notmuch-fcc-dirs set to a string"
-test_emacs "(let ((notmuch-fcc-dirs \"sent-string\"))
- (notmuch-mua-mail)
- (test-output))"
-cat <<EOF >EXPECTED
-From: Notmuch Test Suite <test_suite@notmuchmail.org>
-To:
-Subject:
-Fcc: ${MAIL_DIR}/sent-string
---text follows this line--
-EOF
-test_expect_equal_file OUTPUT EXPECTED
-
-# Make more FCC maildirs specific for the next test
-mkdir -p mail/sent-list-match/cur
-mkdir -p mail/sent-list-match/new
-mkdir -p mail/sent-list-match/tmp
-mkdir -p mail/failure/cur
-mkdir -p mail/failure/new
-mkdir -p mail/failure/tmp
-
-test_begin_subtest "notmuch-fcc-dirs set to a list (with match)"
-test_emacs "(let ((notmuch-fcc-dirs
- '((\"notmuchmail.org\" . \"sent-list-match\")
- (\".*\" . \"failure\"))))
- (notmuch-mua-mail)
- (test-output))"
-cat <<EOF >EXPECTED
-From: Notmuch Test Suite <test_suite@notmuchmail.org>
-To:
-Subject:
-Fcc: ${MAIL_DIR}/sent-list-match
---text follows this line--
-EOF
-test_expect_equal_file OUTPUT EXPECTED
-
-# Make another FCC maildir specific for the next test
-mkdir -p mail/sent-list-catch-all/cur
-mkdir -p mail/sent-list-catch-all/new
-mkdir -p mail/sent-list-catch-all/tmp
-
-test_begin_subtest "notmuch-fcc-dirs set to a list (catch-all)"
-test_emacs "(let ((notmuch-fcc-dirs
- '((\"example.com\" . \"failure\")
- (\".*\" . \"sent-list-catch-all\"))))
- (notmuch-mua-mail)
- (test-output))"
-cat <<EOF >EXPECTED
-From: Notmuch Test Suite <test_suite@notmuchmail.org>
-To:
-Subject:
-Fcc: ${MAIL_DIR}/sent-list-catch-all
---text follows this line--
-EOF
-test_expect_equal_file OUTPUT EXPECTED
-
-test_begin_subtest "notmuch-fcc-dirs set to a list (no match)"
-test_emacs "(let ((notmuch-fcc-dirs
- '((\"example.com\" . \"failure\")
- (\"nomatchhere.net\" . \"failure\"))))
- (notmuch-mua-mail)
- (test-output))"
-cat <<EOF >EXPECTED
-From: Notmuch Test Suite <test_suite@notmuchmail.org>
-To:
-Subject:
---text follows this line--
-EOF
-test_expect_equal_file OUTPUT EXPECTED
-
-test_begin_subtest "Reply within emacs"
-test_emacs '(let ((message-hidden-headers ''()))
- (notmuch-search "subject:\"testing message sent via SMTP\"")
- (notmuch-test-wait)
- (notmuch-search-reply-to-thread)
- (test-output))'
-sed -i -e 's/^In-Reply-To: <.*>$/In-Reply-To: <XXX>/' OUTPUT
-sed -i -e 's/^References: <.*>$/References: <XXX>/' OUTPUT
-sed -i -e 's,^User-Agent: Notmuch/.* Emacs/.*,User-Agent: Notmuch/XXX Emacs/XXX,' OUTPUT
-cat <<EOF >EXPECTED
-From: Notmuch Test Suite <test_suite@notmuchmail.org>
-To: user@example.com
-Subject: Re: Testing message sent via SMTP
-In-Reply-To: <XXX>
-Fcc: ${MAIL_DIR}/sent
-References: <XXX>
-User-Agent: Notmuch/XXX Emacs/XXX
---text follows this line--
-Notmuch Test Suite <test_suite@notmuchmail.org> writes:
-
-> This is a test that messages are sent via SMTP
-EOF
-test_expect_equal_file OUTPUT EXPECTED
-
-test_begin_subtest "Reply from alternate address within emacs"
-add_message '[from]="Sender <sender@example.com>"' \
- [to]=test_suite_other@notmuchmail.org
-
-test_emacs "(let ((message-hidden-headers '()))
- (notmuch-search \"id:\\\"${gen_msg_id}\\\"\")
- (notmuch-test-wait)
- (notmuch-search-reply-to-thread)
- (test-output))"
-sed -i -e 's,^User-Agent: Notmuch/.* Emacs/.*,User-Agent: Notmuch/XXX Emacs/XXX,' OUTPUT
-cat <<EOF >EXPECTED
-From: Notmuch Test Suite <test_suite_other@notmuchmail.org>
-To: Sender <sender@example.com>
-Subject: Re: ${test_subtest_name}
-In-Reply-To: <${gen_msg_id}>
-Fcc: ${MAIL_DIR}/sent
-References: <${gen_msg_id}>
-User-Agent: Notmuch/XXX Emacs/XXX
---text follows this line--
-Sender <sender@example.com> writes:
-
-> This is just a test message (#${gen_msg_cnt})
-EOF
-test_expect_equal_file OUTPUT EXPECTED
-
-test_begin_subtest "Reply from address in named group list within emacs"
-add_message '[from]="Sender <sender@example.com>"' \
- '[to]=group:test_suite@notmuchmail.org,someone@example.com\;' \
- [cc]=test_suite_other@notmuchmail.org
-
-test_emacs "(let ((message-hidden-headers '()))
- (notmuch-search \"id:\\\"${gen_msg_id}\\\"\")
- (notmuch-test-wait)
- (notmuch-search-reply-to-thread)
- (test-output))"
-sed -i -e 's,^User-Agent: Notmuch/.* Emacs/.*,User-Agent: Notmuch/XXX Emacs/XXX,' OUTPUT
-cat <<EOF >EXPECTED
-From: Notmuch Test Suite <test_suite@notmuchmail.org>
-To: Sender <sender@example.com>, someone@example.com
-Subject: Re: ${test_subtest_name}
-In-Reply-To: <${gen_msg_id}>
-Fcc: ${MAIL_DIR}/sent
-References: <${gen_msg_id}>
-User-Agent: Notmuch/XXX Emacs/XXX
---text follows this line--
-Sender <sender@example.com> writes:
-
-> This is just a test message (#${gen_msg_cnt})
-EOF
-test_expect_equal_file OUTPUT EXPECTED
-
-test_begin_subtest "Reply within emacs to a multipart/mixed message"
-test_emacs '(let ((message-hidden-headers ''()))
- (notmuch-show "id:20091118002059.067214ed@hikari")
- (notmuch-show-reply)
- (test-output))'
-sed -i -e 's,^User-Agent: Notmuch/.* Emacs/.*,User-Agent: Notmuch/XXX Emacs/XXX,' OUTPUT
-cat <<EOF >EXPECTED
-From: Notmuch Test Suite <test_suite@notmuchmail.org>
-To: Adrian Perez de Castro <aperez@igalia.com>, notmuch@notmuchmail.org
-Subject: Re: [notmuch] Introducing myself
-In-Reply-To: <20091118002059.067214ed@hikari>
-Fcc: ${MAIL_DIR}/sent
-References: <20091118002059.067214ed@hikari>
-User-Agent: Notmuch/XXX Emacs/XXX
---text follows this line--
-Adrian Perez de Castro <aperez@igalia.com> writes:
-
-> Hello to all,
->
-> I have just heard about Not Much today in some random Linux-related news
-> site (LWN?), my name is Adrian Perez and I work as systems administrator
-> (although I can do some code as well :P). I have always thought that the
-> ideas behind Sup were great, but after some time using it, I got tired of
-> the oddities that it has. I also do not like doing things like having to
-> install Ruby just for reading and sorting mails. Some time ago I thought
-> about doing something like Not Much and in fact I played a bit with the
-> Python+Xapian and the Python+Whoosh combinations, because I find relaxing
-> to code things in Python when I am not working and also it is installed
-> by default on most distribution. I got to have some mailboxes indexed and
-> basic searching working a couple of months ago. Lately I have been very
-> busy and had no time for coding, and them... boom! Not Much appears -- and
-> it is almost exactly what I was trying to do, but faster. I have been
-> playing a bit with Not Much today, and I think it has potential.
->
-> Also, I would like to share one idea I had in mind, that you might find
-> interesting: One thing I have found very annoying is having to re-tag my
-> mail when the indexes get b0rked (it happened a couple of times to me while
-> using Sup), so I was planning to mails as read/unread and adding the tags
-> not just to the index, but to the mail text itself, e.g. by adding a
-> "X-Tags" header field or by reusing the "Keywords" one. This way, the index
-> could be totally recreated by re-reading the mail directories, and this
-> would also allow to a tools like OfflineIMAP [1] to get the mails into a
-> local maildir, tagging and indexing the mails with the e-mail reader and
-> then syncing back the messages with the "X-Tags" header to the IMAP server.
-> This would allow to use the mail reader from a different computer and still
-> have everything tagged finely.
->
-> Best regards,
->
->
-> ---
-> [1] http://software.complete.org/software/projects/show/offlineimap
->
-> --
-> Adrian Perez de Castro <aperez@igalia.com>
-> Igalia - Free Software Engineering
-> _______________________________________________
-> notmuch mailing list
-> notmuch@notmuchmail.org
-> http://notmuchmail.org/mailman/listinfo/notmuch
-EOF
-test_expect_equal_file OUTPUT EXPECTED
-
-test_begin_subtest "Reply within emacs to a multipart/alternative message"
-test_emacs '(let ((message-hidden-headers ''()))
- (notmuch-show "id:cf0c4d610911171136h1713aa59w9cf9aa31f052ad0a@mail.gmail.com")
- (notmuch-show-reply)
- (test-output))'
-sed -i -e 's,^User-Agent: Notmuch/.* Emacs/.*,User-Agent: Notmuch/XXX Emacs/XXX,' OUTPUT
-cat <<EOF >EXPECTED
-From: Notmuch Test Suite <test_suite@notmuchmail.org>
-To: Alex Botero-Lowry <alex.boterolowry@gmail.com>, notmuch@notmuchmail.org
-Subject: Re: [notmuch] preliminary FreeBSD support
-In-Reply-To: <cf0c4d610911171136h1713aa59w9cf9aa31f052ad0a@mail.gmail.com>
-Fcc: ${MAIL_DIR}/sent
-References: <cf0c4d610911171136h1713aa59w9cf9aa31f052ad0a@mail.gmail.com>
-User-Agent: Notmuch/XXX Emacs/XXX
---text follows this line--
-Alex Botero-Lowry <alex.boterolowry@gmail.com> writes:
-
-> I saw the announcement this morning, and was very excited, as I had been
-> hoping sup would be turned into a library,
-> since I like the concept more than the UI (I'd rather an emacs interface).
->
-> I did a preliminary compile which worked out fine, but
-> sysconf(_SC_SC_GETPW_R_SIZE_MAX) returns -1 on
-> FreeBSD, so notmuch_config_open segfaulted.
->
-> Attached is a patch that supplies a default buffer size of 64 in cases where
-> -1 is returned.
->
-> http://www.opengroup.org/austin/docs/austin_328.txt - seems to indicate this
-> is acceptable behavior,
-> and http://mail-index.netbsd.org/pkgsrc-bugs/2006/06/07/msg016808.htmlspecifically
-> uses 64 as the
-> buffer size.
-> _______________________________________________
-> notmuch mailing list
-> notmuch@notmuchmail.org
-> http://notmuchmail.org/mailman/listinfo/notmuch
-EOF
-test_expect_equal_file OUTPUT EXPECTED
-
-test_begin_subtest "Reply within emacs to an html-only message"
-add_message '[content-type]="text/html"' \
- '[body]="Hi,<br />This is an <b>HTML</b> test message.<br /><br />OK?"'
-test_emacs "(let ((message-hidden-headers '()) (mm-text-html-renderer 'html2text))
- (notmuch-show \"id:${gen_msg_id}\")
- (notmuch-show-reply)
- (test-output))"
-sed -i -e 's,^User-Agent: Notmuch/.* Emacs/.*,User-Agent: Notmuch/XXX Emacs/XXX,' OUTPUT
-cat <<EOF >EXPECTED
-From: Notmuch Test Suite <test_suite@notmuchmail.org>
-To:
-Subject: Re: Reply within emacs to an html-only message
-In-Reply-To: <${gen_msg_id}>
-Fcc: ${MAIL_DIR}/sent
-References: <${gen_msg_id}>
-User-Agent: Notmuch/XXX Emacs/XXX
---text follows this line--
-Notmuch Test Suite <test_suite@notmuchmail.org> writes:
-
-> Hi,This is an HTML test message.OK?
-EOF
-test_expect_equal_file OUTPUT EXPECTED
-
-test_begin_subtest "Quote MML tags in reply"
-message_id='test-emacs-mml-quoting@message.id'
-add_message [id]="$message_id" \
- "[subject]='$test_subtest_name'" \
- '[body]="<#part disposition=inline>"'
-test_emacs "(let ((message-hidden-headers '()))
- (notmuch-show \"id:$message_id\")
- (notmuch-show-reply)
- (test-output))"
-sed -i -e 's,^User-Agent: Notmuch/.* Emacs/.*,User-Agent: Notmuch/XXX Emacs/XXX,' OUTPUT
-cat <<EOF >EXPECTED
-From: Notmuch Test Suite <test_suite@notmuchmail.org>
-To:
-Subject: Re: Quote MML tags in reply
-In-Reply-To: <test-emacs-mml-quoting@message.id>
-Fcc: ${MAIL_DIR}/sent
-References: <test-emacs-mml-quoting@message.id>
-User-Agent: Notmuch/XXX Emacs/XXX
---text follows this line--
-Notmuch Test Suite <test_suite@notmuchmail.org> writes:
-
-> <#!part disposition=inline>
-EOF
-test_expect_equal_file OUTPUT EXPECTED
-
-test_begin_subtest "Save attachment from within emacs using notmuch-show-save-attachments"
-# save as archive to test that Emacs does not re-compress .gz
-test_emacs '(let ((standard-input "\"attachment1.gz\""))
- (notmuch-show "id:cf0c4d610911171136h1713aa59w9cf9aa31f052ad0a@mail.gmail.com")
- (notmuch-show-save-attachments))'
-test_expect_equal_file attachment1.gz "$EXPECTED/attachment"
-
-test_begin_subtest "Save attachment from within emacs using notmuch-show-save-part"
-# save as archive to test that Emacs does not re-compress .gz
-test_emacs '(let ((standard-input "\"attachment2.gz\""))
- (notmuch-show "id:cf0c4d610911171136h1713aa59w9cf9aa31f052ad0a@mail.gmail.com")
- (search-forward "0001-Deal-with")
- (notmuch-show-save-part))'
-test_expect_equal_file attachment2.gz "$EXPECTED/attachment"
-
-test_begin_subtest "Save 8bit attachment from within emacs using notmuch-show-save-attachments"
-
-add_message '[subject]="Attachment with 8bit chars"' \
- '[header]="MIME-Version: 1.0"' \
- '[content-type]="multipart/mixed; boundary=\"abcd\""' \
- '[body]="--abcd
-Content-Type: text/plain
-
-Attachment follows:
-
---abcd
-Content-Type: application/octet-stream; name=\"sample\"
-Content-Transfer-Encoding: 8bit
-Content-Disposition: attachment; filename=\"sample\"
-
-“¡ Hey ! It compiles ¡ Ship it !”
-
---abcd--
-"'
-test_emacs '(notmuch-show "id:'"${gen_msg_id}"'")
- (delete-file "OUTPUT")
- (let ((standard-input "\"OUTPUT\""))
- (notmuch-show-save-attachments))'
-
-test_expect_equal "$(cat OUTPUT)" '“¡ Hey ! It compiles ¡ Ship it !”'
-
-test_begin_subtest "View raw message within emacs"
-test_emacs '(notmuch-show "id:cf0c4d610911171136h1713aa59w9cf9aa31f052ad0a@mail.gmail.com")
- (notmuch-show-view-raw-message)
- (test-output)'
-test_expect_equal_file OUTPUT $EXPECTED/raw-message-cf0c4d-52ad0a
-
-test_begin_subtest "Hiding/showing signature in notmuch-show view"
-maildir_storage_thread=$(notmuch search --output=threads id:20091117190054.GU3165@dottiness.seas.harvard.edu)
-test_emacs "(notmuch-show \"$maildir_storage_thread\")
- (search-forward \"Click/Enter to show.\")
- (button-activate (button-at (point)))
- (search-backward \"Click/Enter to hide.\")
- (button-activate (button-at (point)))
- (test-output)"
-test_expect_equal_file OUTPUT $EXPECTED/notmuch-show-thread-maildir-storage
-
-test_begin_subtest "Detection and hiding of top-post quoting of message"
-add_message '[subject]="The problem with top-posting"' \
- [id]=top-post-target \
- '[body]="A: Because it messes up the order in which people normally read text.
-Q: Why is top-posting such a bad thing?
-A: Top-posting.
-Q: What is the most annoying thing in e-mail?"'
-add_message '[from]="Top Poster <top@poster.com>"' \
- [in-reply-to]=top-post-target \
- [references]=top-post-target \
- '[subject]="Re: The problem with top-posting"' \
- '[body]="Thanks for the advice! I will be sure to put it to good use.
-
--Top Poster
-
------ Original Message -----
-From: Notmuch Test Suite <test_suite@notmuchmail.org>
-To: Notmuch Test Suite <test_suite@notmuchmai.org>
-Sent: Fri, 05 Jan 2001 15:43:57 +0000
-Subject: The problem with top-posting
-
-Q: Why is top-posting such a bad thing?
-A: Top-posting.
-Q: What is the most annoying thing in e-mail?"'
-test_emacs "(notmuch-show \"top-posting\")
- (test-visible-output \"OUTPUT.raw\")"
-echo "Notmuch Test Suite <test_suite@notmuchmail.org> (2001-01-05) (inbox)
-Subject: The problem with top-posting
-To: Notmuch Test Suite <test_suite@notmuchmail.org>
-Date: GENERATED_DATE
-
-A: Because it messes up the order in which people normally read text.
-Q: Why is top-posting such a bad thing?
-A: Top-posting.
-Q: What is the most annoying thing in e-mail?
-Top Poster <top@poster.com> (2001-01-05) (inbox unread)
-Subject: Re: The problem with top-posting
-To: Notmuch Test Suite <test_suite@notmuchmail.org>
-Date: GENERATED_DATE
-
-Thanks for the advice! I will be sure to put it to good use.
-
--Top Poster
-
-[ 9-line hidden original message. Click/Enter to show. ]" > EXPECTED
-notmuch_date_sanitize < OUTPUT.raw > OUTPUT
-test_expect_equal_file OUTPUT EXPECTED
-
-test_begin_subtest "Hiding message in notmuch-show view"
-test_emacs '(notmuch-show "id:f35dbb950911171438k5df6eb56k77b6c0944e2e79ae@mail.gmail.com")
- (notmuch-show-toggle-message)
- (test-visible-output)'
-test_expect_equal_file OUTPUT $EXPECTED/notmuch-show-thread-with-hidden-messages
-
-test_begin_subtest "Hiding message with visible citation in notmuch-show view"
-test_emacs '(notmuch-show "id:f35dbb950911171438k5df6eb56k77b6c0944e2e79ae@mail.gmail.com")
- (search-forward "Click/Enter to show.")
- (button-activate (button-at (point)))
- (notmuch-show-toggle-message)
- (test-visible-output)'
-test_expect_equal_file OUTPUT $EXPECTED/notmuch-show-thread-with-hidden-messages
-
-test_begin_subtest "notmuch-show: show message headers"
-test_emacs \
- '(let ((notmuch-message-headers '\''("Subject" "To" "Cc" "Date"))
- (notmuch-message-headers-visible t))
- (notmuch-show "id:f35dbb950911171438k5df6eb56k77b6c0944e2e79ae@mail.gmail.com")
- (test-visible-output))'
-test_expect_equal_file OUTPUT $EXPECTED/notmuch-show-message-with-headers-visible
-
-test_begin_subtest "notmuch-show: hide message headers"
-test_emacs \
- '(let ((notmuch-message-headers '\''("Subject" "To" "Cc" "Date"))
- (notmuch-message-headers-visible nil))
- (notmuch-show "id:f35dbb950911171438k5df6eb56k77b6c0944e2e79ae@mail.gmail.com")
- (test-visible-output))'
-test_expect_equal_file OUTPUT $EXPECTED/notmuch-show-message-with-headers-hidden
-
-test_begin_subtest "notmuch-show: hide message headers (w/ notmuch-show-toggle-visibility-headers)"
-test_emacs \
- '(let ((notmuch-message-headers '\''("Subject" "To" "Cc" "Date"))
- (notmuch-message-headers-visible t))
- (notmuch-show "id:f35dbb950911171438k5df6eb56k77b6c0944e2e79ae@mail.gmail.com")
- (notmuch-show-toggle-visibility-headers)
- (test-visible-output))'
-test_expect_equal_file OUTPUT $EXPECTED/notmuch-show-message-with-headers-hidden
-
-test_begin_subtest "notmuch-show: collapse all messages in thread"
-test_emacs '(notmuch-show "id:f35dbb950911171435ieecd458o853c873e35f4be95@mail.gmail.com")
- (let ((current-prefix-arg t))
- (notmuch-show-open-or-close-all)
- (test-visible-output))'
-test_expect_equal_file OUTPUT $EXPECTED/notmuch-show-thread-with-all-messages-collapsed
-
-test_begin_subtest "notmuch-show: uncollapse all messages in thread"
-test_emacs '(notmuch-show "id:f35dbb950911171435ieecd458o853c873e35f4be95@mail.gmail.com")
- (notmuch-show-open-or-close-all)
- (test-visible-output)'
-test_expect_equal_file OUTPUT $EXPECTED/notmuch-show-thread-with-all-messages-uncollapsed
-
-test_begin_subtest "Stashing in notmuch-show"
-add_message '[date]="Sat, 01 Jan 2000 12:00:00 -0000"' \
- '[from]="Some One <someone@somewhere.org>"' \
- '[to]="Some One Else <notsomeone@somewhere.org>"' \
- '[cc]="Notmuch <notmuch@notmuchmail.org>"' \
- '[subject]="Stash my stashables"' \
- '[id]="bought"' \
- '[body]="Unable to stash body. Where did you get it in the first place?!?"'
-notmuch tag +stashtest id:${gen_msg_id}
-test_emacs '(notmuch-show "id:\"bought\"")
- (notmuch-show-stash-date)
- (notmuch-show-stash-from)
- (notmuch-show-stash-to)
- (notmuch-show-stash-cc)
- (notmuch-show-stash-subject)
- (notmuch-show-stash-message-id)
- (notmuch-show-stash-message-id-stripped)
- (notmuch-show-stash-tags)
- (notmuch-show-stash-filename)
- (notmuch-show-stash-mlarchive-link "Gmane")
- (notmuch-show-stash-mlarchive-link "MARC")
- (notmuch-show-stash-mlarchive-link "Mail Archive, The")
- (switch-to-buffer
- (generate-new-buffer "*test-stashing*"))
- (dotimes (i 12)
- (yank)
- (insert "\n")
- (rotate-yank-pointer 1))
- (reverse-region (point-min) (point-max))
- (test-output)'
-cat <<EOF >EXPECTED
-Sat, 01 Jan 2000 12:00:00 +0000
-Some One <someone@somewhere.org>
-Some One Else <notsomeone@somewhere.org>
-Notmuch <notmuch@notmuchmail.org>
-Stash my stashables
-id:bought
-bought
-inbox,stashtest
-${gen_msg_filename}
-http://mid.gmane.org/bought
-http://marc.info/?i=bought
-http://mail-archive.com/search?l=mid&q=bought
-EOF
-test_expect_equal_file OUTPUT EXPECTED
-
-test_begin_subtest "Stashing in notmuch-search"
-test_emacs '(notmuch-search "id:\"bought\"")
- (notmuch-test-wait)
- (notmuch-search-stash-thread-id)
- (switch-to-buffer
- (generate-new-buffer "*test-stashing*"))
- (yank)
- (test-output)'
-sed -i -e 's/^thread:.*$/thread:XXX/' OUTPUT
-test_expect_equal "$(cat OUTPUT)" "thread:XXX"
-
-test_begin_subtest 'notmuch-show-advance-and-archive with invisible signature'
-message1='id:20091118010116.GC25380@dottiness.seas.harvard.edu'
-message2='id:1258491078-29658-1-git-send-email-dottedmag@dottedmag.net'
-test_emacs "(notmuch-show \"$message2\")
- (test-output \"EXPECTED\")"
-test_emacs "(notmuch-search \"$message1 or $message2\")
- (notmuch-test-wait)
- (notmuch-search-show-thread)
- (goto-char (point-max))
- (redisplay)
- (notmuch-show-advance-and-archive)
- (test-output)"
-test_expect_equal_file OUTPUT EXPECTED
-
-test_begin_subtest "Refresh show buffer"
-test_emacs '(notmuch-show "id:f35dbb950911171438k5df6eb56k77b6c0944e2e79ae@mail.gmail.com")
- (test-visible-output "EXPECTED")
- (notmuch-show-refresh-view)
- (test-visible-output)'
-test_expect_equal_file OUTPUT EXPECTED
-
-test_begin_subtest "Refresh modified show buffer"
-test_emacs '(notmuch-show "id:f35dbb950911171438k5df6eb56k77b6c0944e2e79ae@mail.gmail.com")
- (notmuch-show-toggle-message)
- (notmuch-show-next-message)
- (notmuch-show-toggle-message)
- (test-visible-output "EXPECTED")
- (notmuch-show-refresh-view)
- (test-visible-output)'
-test_expect_equal_file OUTPUT EXPECTED
-
-test_begin_subtest "Do not call notmuch for non-inlinable application/mpeg parts"
-id='message-with-application/mpeg-attachment@notmuchmail.org'
-emacs_fcc_message \
- 'Message with application/mpeg attachment' \
- '' \
- "(message-goto-eoh)
- (insert \"Message-ID: <$id>\n\")
- (message-goto-body)
- (mml-insert-part \"application/mpeg\")
- (insert \"a fake mp3 file\")"
-notmuch_counter_reset
-test_emacs "(let ((notmuch-command \"$notmuch_counter_command\"))
- (notmuch-show \"id:$id\"))"
-test_expect_equal $(notmuch_counter_value) 1
-
-test_begin_subtest "Do not call notmuch for non-inlinable audio/mpeg parts"
-id='message-with-audio/mpeg-attachment@notmuchmail.org'
-emacs_fcc_message \
- 'Message with audio/mpeg attachment' \
- '' \
- "(message-goto-eoh)
- (insert \"Message-ID: <$id>\n\")
- (message-goto-body)
- (mml-insert-part \"audio/mpeg\")
- (insert \"a fake mp3 file\")"
-notmuch_counter_reset
-test_emacs "(let ((notmuch-command \"$notmuch_counter_command\"))
- (notmuch-show \"id:$id\"))"
-test_expect_equal $(notmuch_counter_value) 1
-
-test_begin_subtest "notmuch-hello-mode hook is called"
-counter=$(test_emacs \
- '(let ((notmuch-hello-mode-hook-counter 0))
- (kill-buffer "*notmuch-hello*")
- (notmuch-hello)
- notmuch-hello-mode-hook-counter)'
-)
-test_expect_equal "$counter" 1
-
-test_begin_subtest "notmuch-hello-mode hook is not called on updates"
-counter=$(test_emacs \
- '(let ((notmuch-hello-mode-hook-counter 0))
- (kill-buffer "*notmuch-hello*")
- (notmuch-hello)
- (notmuch-hello-update)
- notmuch-hello-mode-hook-counter)'
-)
-test_expect_equal "$counter" 1
-
-test_begin_subtest "notmuch-hello-refresh hook is called"
-counter=$(test_emacs \
- '(let ((notmuch-hello-refresh-hook-counter 0))
- (kill-buffer "*notmuch-hello*")
- (notmuch-hello)
- notmuch-hello-refresh-hook-counter)'
-)
-test_expect_equal "$counter" 1
-
-test_begin_subtest "notmuch-hello-refresh hook is called on updates"
-counter=$(test_emacs \
- '(let ((notmuch-hello-refresh-hook-counter 0))
- (kill-buffer "*notmuch-hello*")
- (notmuch-hello)
- (notmuch-hello-update)
- notmuch-hello-refresh-hook-counter)'
-)
-test_expect_equal "$counter" 2
-
-
-add_message '[subject]="HTML mail with images"' \
- '[content-type]="multipart/related; boundary=abcd"' \
- '[body]="--abcd
-Content-Type: text/html
-
-<img src="cid:330@goomoji.gmail"> smiley
-
---abcd
-Content-Type: image/gif
-Content-Transfer-Encoding: base64
-Content-ID: <330@goomoji.gmail>
-
-R0lGODlhDAAMAKIFAF5LAP/zxAAAANyuAP/gaP///wAAAAAAACH5BAEAAAUALAAAAAAMAAwAAAMl
-WLPcGjDKFYi9lxKBOaGcF35DhWHamZUW0K4mAbiwWtuf0uxFAgA7
---abcd--"'
-test_emacs "(let ((mm-text-html-renderer
- (if (assq 'shr mm-text-html-renderer-alist)
- 'shr 'html2text)))
- (notmuch-show \"id:${gen_msg_id}\"))
- (test-output)" > /dev/null
-# Different Emacs versions and renderers give very different results,
-# so just check that something reasonable showed up. We first cat the
-# output so the test framework will print it if the test fails.
-test_expect_success "Rendering HTML mail with images" \
- 'cat OUTPUT && grep -q smiley OUTPUT'
-
-
-test_begin_subtest "Search handles subprocess error exit codes"
-cat > notmuch_fail <<EOF
-#!/bin/sh
-echo '()'
-exit 1
-EOF
-chmod a+x notmuch_fail
-test_emacs "(let ((notmuch-command \"$PWD/notmuch_fail\"))
- (with-current-buffer \"*Messages*\" (erase-buffer))
- (with-current-buffer (get-buffer-create \"*Notmuch errors*\")
- (erase-buffer))
- (notmuch-search \"tag:inbox\")
- (notmuch-test-wait)
- (with-current-buffer \"*Messages*\"
- (test-output \"MESSAGES\"))
- (with-current-buffer \"*Notmuch errors*\"
- (test-output \"ERROR\"))
- (test-output))"
-
-test_expect_equal "$(notmuch_emacs_error_sanitize notmuch_fail OUTPUT MESSAGES ERROR)" "\
-=== OUTPUT ===
-End of search results.
-=== MESSAGES ===
-YYY/notmuch_fail exited with status 1 (see *Notmuch errors* for more details)
-=== ERROR ===
-[XXX]
-YYY/notmuch_fail exited with status 1
-command: YYY/notmuch_fail search --format\=sexp --format-version\=2 --sort\=newest-first tag\:inbox
-exit status: 1"
-
-test_begin_subtest "Search handles subprocess warnings"
-cat > notmuch_fail <<EOF
-#!/bin/sh
-echo '()'
-echo This is a warning >&2
-echo This is another warning >&2
-exit 0
-EOF
-chmod a+x notmuch_fail
-test_emacs "(let ((notmuch-command \"$PWD/notmuch_fail\"))
- (with-current-buffer \"*Messages*\" (erase-buffer))
- (with-current-buffer (get-buffer-create \"*Notmuch errors*\")
- (erase-buffer))
- (notmuch-search \"tag:inbox\")
- (notmuch-test-wait)
- (with-current-buffer \"*Messages*\"
- (test-output \"MESSAGES\"))
- (with-current-buffer \"*Notmuch errors*\"
- (test-output \"ERROR\"))
- (test-output))"
-sed -i -e 's/^\[.*\]$/[XXX]/' ERROR
-test_expect_equal "$(cat OUTPUT; echo ---; cat MESSAGES; echo ---; cat ERROR)" "\
-End of search results.
----
-This is a warning (see *Notmuch errors* for more details)
----
-[XXX]
-This is a warning
-This is another warning"
-
-test_begin_subtest "Search thread tag operations are race-free"
-add_message '[subject]="Search race test"'
-gen_msg_id_1=$gen_msg_id
-generate_message '[in-reply-to]="<'$gen_msg_id_1'>"' \
- '[references]="<'$gen_msg_id_1'>"' \
- '[subject]="Search race test two"'
-test_emacs '(notmuch-search "subject:\"search race test\"")
- (notmuch-test-wait)
- (notmuch-poll)
- (execute-kbd-macro "+search-thread-race-tag")'
-output=$(notmuch search --output=messages 'tag:search-thread-race-tag')
-test_expect_equal "$output" "id:$gen_msg_id_1"
-
-test_begin_subtest "Search global tag operations are race-free"
-generate_message '[in-reply-to]="<'$gen_msg_id_1'>"' \
- '[references]="<'$gen_msg_id_1'>"' \
- '[subject]="Re: Search race test"'
-test_emacs '(notmuch-search "subject:\"search race test\" -subject:two")
- (notmuch-test-wait)
- (notmuch-poll)
- (execute-kbd-macro "*+search-global-race-tag")'
-output=$(notmuch search --output=messages 'tag:search-global-race-tag')
-test_expect_equal "$output" "id:$gen_msg_id_1"
-
-test_done
+++ /dev/null
-#!/usr/bin/env bash
-
-test_description="emacs address cleaning"
-. ./test-lib.sh
-
-test_begin_subtest "notmuch-test-address-clean part 1"
-test_emacs_expect_t '(notmuch-test-address-cleaning-1)'
-
-test_begin_subtest "notmuch-test-address-clean part 2"
-test_emacs_expect_t '(notmuch-test-address-cleaning-2)'
-
-test_begin_subtest "notmuch-test-address-clean part 3"
-test_emacs_expect_t '(notmuch-test-address-cleaning-3)'
-
-test_done
+++ /dev/null
-#!/usr/bin/env bash
-
-test_description="emacs notmuch-hello view"
-. ./test-lib.sh
-
-EXPECTED=$TEST_DIRECTORY/emacs.expected-output
-
-add_email_corpus
-
-test_begin_subtest "User-defined section with inbox tag"
-test_emacs "(let ((notmuch-hello-sections
- (list (lambda () (notmuch-hello-insert-searches
- \"Test\" '((\"inbox\" . \"tag:inbox\")))))))
- (notmuch-hello)
- (test-output))"
-test_expect_equal_file OUTPUT $EXPECTED/notmuch-hello-new-section
-
-test_begin_subtest "User-defined section with empty, hidden entry"
-test_emacs "(let ((notmuch-hello-sections
- (list (lambda () (notmuch-hello-insert-searches
- \"Test-with-empty\"
- '((\"inbox\" . \"tag:inbox\")
- (\"doesnotexist\" . \"tag:doesnotexist\"))
- :hide-empty-searches t)))))
- (notmuch-hello)
- (test-output))"
-test_expect_equal_file OUTPUT $EXPECTED/notmuch-hello-section-with-empty
-
-test_begin_subtest "User-defined section, unread tag filtered out"
-test_emacs "(let ((notmuch-hello-sections
- (list (lambda () (notmuch-hello-insert-tags-section
- \"Test-with-filtered\"
- :hide-tags '(\"unread\"))))))
- (notmuch-hello)
- (test-output))"
-test_expect_equal_file OUTPUT $EXPECTED/notmuch-hello-section-hidden-tag
-
-test_begin_subtest "User-defined section, different query for counts"
-test_emacs "(let ((notmuch-hello-sections
- (list (lambda () (notmuch-hello-insert-tags-section
- \"Test-with-counts\"
- :filter-count \"tag:signed\")))))
- (notmuch-hello)
- (test-output))"
-test_expect_equal_file OUTPUT $EXPECTED/notmuch-hello-section-counts
-
-test_begin_subtest "Empty custom tags section"
-test_emacs "(let* ((widget (widget-create 'notmuch-hello-tags-section))
- (notmuch-hello-sections (list (widget-value widget))))
- (notmuch-hello)
- (test-output))"
-test_expect_equal_file OUTPUT $EXPECTED/notmuch-hello-empty-custom-tags-section
-
-test_begin_subtest "Empty custom queries section"
-test_emacs "(let* ((widget (widget-create 'notmuch-hello-query-section))
- (notmuch-hello-sections (list (widget-value widget))))
- (notmuch-hello)
- (test-output))"
-test_expect_equal_file OUTPUT $EXPECTED/notmuch-hello-empty-custom-queries-section
-
-test_begin_subtest "Column alignment for tag/queries with long names"
-tag=a-very-long-tag # length carefully calculated for 80 characters window width
-notmuch tag +$tag '*'
-test_emacs '(notmuch-hello)
- (test-output)'
-notmuch tag -$tag '*'
-test_expect_equal_file OUTPUT $EXPECTED/notmuch-hello-long-names
-
-test_done
+++ /dev/null
-#!/usr/bin/env bash
-test_description="Emacs with large search results buffer"
-. ./test-lib.sh
-
-x=xxxxxxxxxx # 10
-x=$x$x$x$x$x$x$x$x$x$x # 100
-x=$x$x$x$x$x$x$x$x$x # 900
-
-# We generate a long subject here (over 900 bytes) so that the emacs
-# search results get large quickly. With 30 such messages we should
-# cross several 4kB page boundaries and see the bug.
-n=30
-for i in $(seq 1 $n); do
- # Roughly 100B2 KiB per message. That is, we need two messages in order to
- # exceed the typical size of the pipe buffer (4 KiB on commodity systems).
- generate_message '[subject]="$x $i of $n"'
-done
-
-notmuch new > /dev/null
-
-test_begin_subtest "Ensure that emacs doesn't drop results"
-notmuch search '*' > EXPECTED
-sed -i -e 's/^thread:[0-9a-f]* //' -e 's/;//' -e 's/xx*/[BLOB]/' EXPECTED
-echo 'End of search results.' >> EXPECTED
-
-test_emacs '(notmuch-search "*")
- (notmuch-test-wait)
- (test-output)'
-sed -i -e s', *, ,g' -e 's/xxx*/[BLOB]/g' OUTPUT
-test_expect_equal_file OUTPUT EXPECTED
-
-test_done
+++ /dev/null
-#!/usr/bin/env bash
-
-test_description="emacs notmuch-show view"
-. ./test-lib.sh
-
-EXPECTED=$TEST_DIRECTORY/emacs-show.expected-output
-
-add_email_corpus
-
-test_begin_subtest "Hiding Original Message region at beginning of a message"
-message_id='OriginalMessageHiding.1@notmuchmail.org'
-add_message \
- [id]="$message_id" \
- '[subject]="Hiding Original Message region at beginning of a message"' \
- '[body]="-----Original Message-----
-Text here."'
-
-cat <<EOF >EXPECTED
-Notmuch Test Suite <test_suite@notmuchmail.org> (2001-01-05) (inbox)
-Subject: Hiding Original Message region at beginning of a message
-To: Notmuch Test Suite <test_suite@notmuchmail.org>
-Date: GENERATED_DATE
-
-[ 2-line hidden original message. Click/Enter to show. ]
-EOF
-
-test_emacs "(notmuch-show \"id:$message_id\")
- (test-visible-output \"OUTPUT.raw\")"
-notmuch_date_sanitize < OUTPUT.raw > OUTPUT
-test_expect_equal_file OUTPUT EXPECTED
-
-test_begin_subtest "Bare subject #1"
-output=$(test_emacs '(notmuch-show-strip-re "Re: subject")')
-test_expect_equal "$output" '"subject"'
-
-test_begin_subtest "Bare subject #2"
-output=$(test_emacs '(notmuch-show-strip-re "re:Re: re: Re: re:subject")')
-test_expect_equal "$output" '"subject"'
-
-test_begin_subtest "Bare subject #3"
-output=$(test_emacs '(notmuch-show-strip-re "the cure: fix the regexp")')
-test_expect_equal "$output" '"the cure: fix the regexp"'
-
-test_begin_subtest "don't process cryptographic MIME parts"
-test_emacs '(let ((notmuch-crypto-process-mime nil))
- (notmuch-show "id:20091117203301.GV3165@dottiness.seas.harvard.edu")
- (test-visible-output))'
-test_expect_equal_file OUTPUT $EXPECTED/notmuch-show-process-crypto-mime-parts-off
-
-test_begin_subtest "process cryptographic MIME parts"
-test_emacs '(let ((notmuch-crypto-process-mime t))
- (notmuch-show "id:20091117203301.GV3165@dottiness.seas.harvard.edu")
- (test-visible-output))'
-test_expect_equal_file OUTPUT $EXPECTED/notmuch-show-process-crypto-mime-parts-on
-
-test_begin_subtest "process cryptographic MIME parts (w/ notmuch-show-toggle-process-crypto)"
-test_emacs '(let ((notmuch-crypto-process-mime nil))
- (notmuch-show "id:20091117203301.GV3165@dottiness.seas.harvard.edu")
- (notmuch-show-toggle-process-crypto)
- (test-visible-output))'
-test_expect_equal_file OUTPUT $EXPECTED/notmuch-show-process-crypto-mime-parts-on
-
-test_begin_subtest "notmuch-show: don't elide non-matching messages"
-test_emacs '(let ((notmuch-show-only-matching-messages nil))
- (notmuch-search "from:lars@seas.harvard.edu and subject:\"Maildir storage\"")
- (notmuch-test-wait)
- (notmuch-search-show-thread)
- (notmuch-test-wait)
- (test-visible-output))'
-test_expect_equal_file OUTPUT $EXPECTED/notmuch-show-elide-non-matching-messages-off
-
-test_begin_subtest "notmuch-show: elide non-matching messages"
-test_emacs '(let ((notmuch-show-only-matching-messages t))
- (notmuch-search "from:lars@seas.harvard.edu and subject:\"Maildir storage\"")
- (notmuch-test-wait)
- (notmuch-search-show-thread)
- (notmuch-test-wait)
- (test-visible-output))'
-test_expect_equal_file OUTPUT $EXPECTED/notmuch-show-elide-non-matching-messages-on
-
-test_begin_subtest "notmuch-show: elide non-matching messages (w/ notmuch-show-toggle-elide-non-matching)"
-test_emacs '(let ((notmuch-show-only-matching-messages nil))
- (notmuch-search "from:lars@seas.harvard.edu and subject:\"Maildir storage\"")
- (notmuch-test-wait)
- (notmuch-search-show-thread)
- (notmuch-test-wait)
- (notmuch-show-toggle-elide-non-matching)
- (test-visible-output))'
-test_expect_equal_file OUTPUT $EXPECTED/notmuch-show-elide-non-matching-messages-on
-
-test_begin_subtest "notmuch-show: elide non-matching messages (w/ prefix arg to notmuch-show)"
-test_emacs '(let ((notmuch-show-only-matching-messages nil))
- (notmuch-search "from:lars@seas.harvard.edu and subject:\"Maildir storage\"")
- (notmuch-test-wait)
- (notmuch-search-show-thread t)
- (notmuch-test-wait)
- (test-visible-output))'
-test_expect_equal_file OUTPUT $EXPECTED/notmuch-show-elide-non-matching-messages-on
-
-test_begin_subtest "notmuch-show: disable indentation of thread content (w/ notmuch-show-toggle-thread-indentation)"
-test_emacs '(notmuch-search "from:lars@seas.harvard.edu and subject:\"Maildir storage\"")
- (notmuch-test-wait)
- (notmuch-search-show-thread)
- (notmuch-test-wait)
- (notmuch-show-toggle-thread-indentation)
- (test-visible-output)'
-test_expect_equal_file OUTPUT $EXPECTED/notmuch-show-indent-thread-content-off
-
-test_begin_subtest "id buttonization"
-add_message '[body]="
-id:abc
-id:abc.def. id:abc,def, id:abc;def; id:abc:def:
-id:foo@bar.?baz? id:foo@bar!.baz!
-(id:foo@bar.baz) [id:foo@bar.baz]
-id:foo@bar.baz...
-id:2+2=5
-id:=_-:/.[]@$%+
-id:abc)def
-id:ab\"c def
-id:\"abc\"def
-id:\"ab\"\"c\"def
-id:\"ab c\"def
-id:\"abc\".def
-id:\"abc
-\"
-id:)
-id:
-cid:xxx
-mid:abc mid:abc/def
-mid:abc%20def
-mid:abc. mid:abc, mid:abc;"'
-test_emacs '(notmuch-show "id:'$gen_msg_id'")
- (notmuch-test-mark-links)
- (test-visible-output "OUTPUT.raw")'
-cat <<EOF >EXPECTED
-Notmuch Test Suite <test_suite@notmuchmail.org> (2001-01-05) (inbox)
-Subject: id buttonization
-To: Notmuch Test Suite <test_suite@notmuchmail.org>
-Date: GENERATED_DATE
-
-<<id:abc>>
-<<id:abc.def>>. <<id:abc,def>>, <<id:abc;def>>; <<id:abc:def>>:
-<<id:foo@bar.?baz>>? <<id:foo@bar!.baz>>!
-(<<id:foo@bar.baz>>) [<<id:foo@bar.baz>>]
-<<id:foo@bar.baz>>...
-<<id:2+2=5>>
-<<id:=_-:/.[]@$%+>>
-<<id:abc>>)def
-<<id:ab"c>> def
-<<id:"abc">>def
-<<id:"ab""c">>def
-<<id:"ab c">>def
-<<id:"abc">>.def
-id:"abc
-"
-id:)
-id:
-cid:xxx
-<<mid:abc>> <<mid:abc/def>>
-<<mid:abc%20def>>
-<<mid:abc>>. <<mid:abc>>, <<mid:abc>>;
-EOF
-notmuch_date_sanitize < OUTPUT.raw > OUTPUT
-test_expect_equal_file OUTPUT EXPECTED
-
-
-test_begin_subtest "Show handles subprocess errors"
-cat > notmuch_fail <<EOF
-#!/bin/sh
-echo This is output
-echo This is an error >&2
-exit 1
-EOF
-chmod a+x notmuch_fail
-test_emacs "(let ((notmuch-command \"$PWD/notmuch_fail\"))
- (with-current-buffer \"*Messages*\" (erase-buffer))
- (condition-case err
- (notmuch-show \"*\")
- (error (message \"%s\" (second err))))
- (notmuch-test-wait)
- (with-current-buffer \"*Messages*\"
- (test-output \"MESSAGES\"))
- (with-current-buffer \"*Notmuch errors*\"
- (test-output \"ERROR\"))
- (test-output))"
-test_expect_equal "$(notmuch_emacs_error_sanitize notmuch_fail OUTPUT MESSAGES ERROR)" "\
-=== OUTPUT ===
-=== MESSAGES ===
-This is an error (see *Notmuch errors* for more details)
-=== ERROR ===
-[XXX]
-This is an error
-command: YYY/notmuch_fail show --format\\=sexp --format-version\\=1 --exclude\\=false \\' \\* \\'
-exit status: 1
-stderr:
-This is an error
-stdout:
-This is output"
-
-
-test_done
+++ /dev/null
-#!/usr/bin/env bash
-
-test_description="emacs: mail subject to filename"
-. ./test-lib.sh
-
-# emacs server can't be started in a child process with $(test_emacs ...)
-test_emacs '(ignore)' > /dev/null
-
-# test notmuch-wash-subject-to-patch-sequence-number (subject)
-test_begin_subtest "no patch sequence number"
-output=$(test_emacs '(format "%S" (notmuch-wash-subject-to-patch-sequence-number
- "[PATCH] A normal patch subject without numbers"))'
-)
-test_expect_equal "$output" '"nil"'
-
-test_begin_subtest "patch sequence number #1"
-output=$(test_emacs '(notmuch-wash-subject-to-patch-sequence-number
- "[PATCH 2/3] A most regular patch subject")'
-)
-test_expect_equal "$output" 2
-
-test_begin_subtest "patch sequence number #2"
-output=$(test_emacs '(notmuch-wash-subject-to-patch-sequence-number
- " [dummy list prefix] [RFC PATCH v2 13/42] Special prefixes")'
-)
-test_expect_equal "$output" 13
-
-test_begin_subtest "patch sequence number #3"
-output=$(test_emacs '(notmuch-wash-subject-to-patch-sequence-number
- "[PATCH 2/3] [PATCH 032/037] use the last prefix")'
-)
-test_expect_equal "$output" 32
-
-test_begin_subtest "patch sequence number #4"
-output=$(test_emacs '(notmuch-wash-subject-to-patch-sequence-number
- "[dummy list prefix] [PATCH 2/3] PATCH 3/3] do not use a broken prefix")'
-)
-test_expect_equal "$output" 2
-
-test_begin_subtest "patch sequence number #5"
-output=$(test_emacs '(notmuch-wash-subject-to-patch-sequence-number
- "[RFC][PATCH 3/5][PATCH 4/5][PATCH 5/5] A made up test")'
-)
-test_expect_equal "$output" 5
-
-test_begin_subtest "patch sequence number #6"
-output=$(test_emacs '(notmuch-wash-subject-to-patch-sequence-number
- "[PATCH 2/3] this -> [PATCH 3/3] is not a prefix anymore [nor this 4/4]")'
-)
-test_expect_equal "$output" 2
-
-test_begin_subtest "patch sequence number #7"
-output=$(test_emacs '(notmuch-wash-subject-to-patch-sequence-number
- "[liberally accept crapola right before123/456and after] the numbers")'
-)
-test_expect_equal "$output" 123
-
-# test notmuch-wash-subject-to-filename (subject &optional maxlen)
-test_begin_subtest "filename #1"
-output=$(test_emacs '(notmuch-wash-subject-to-filename
- "just a subject line")'
-)
-test_expect_equal "$output" '"just-a-subject-line"'
-
-test_begin_subtest "filename #2"
-output=$(test_emacs '(notmuch-wash-subject-to-filename
- " [any] [prefixes are ] [removed!] from the subject")'
-)
-test_expect_equal "$output" '"from-the-subject"'
-
-test_begin_subtest "filename #3"
-output=$(test_emacs '(notmuch-wash-subject-to-filename
- " leading and trailing space ")'
-)
-test_expect_equal "$output" '"leading-and-trailing-space"'
-
-test_begin_subtest "filename #4"
-output=$(test_emacs '(notmuch-wash-subject-to-filename
- "!# leading ()// &%, and in between_and_trailing garbage ()(&%%")'
-)
-test_expect_equal "$output" '"-leading-and-in-between_and_trailing-garbage"'
-
-test_begin_subtest "filename #5"
-output=$(test_emacs '(notmuch-wash-subject-to-filename
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.-_01234567890")'
-)
-test_expect_equal "$output" '"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.-_01234567890"'
-
-test_begin_subtest "filename #6"
-output=$(test_emacs '(notmuch-wash-subject-to-filename
- "sequences of ... are squashed and trailing are removed ...")'
-)
-test_expect_equal "$output" '"sequences-of-.-are-squashed-and-trailing-are-removed"'
-
-test_begin_subtest "filename #7"
-output=$(test_emacs '(notmuch-wash-subject-to-filename
- "max length test" 1)'
-)
-test_expect_equal "$output" '"m"'
-
-test_begin_subtest "filename #8"
-output=$(test_emacs '(notmuch-wash-subject-to-filename
- "max length test /&(/%&/%%&¤%¤" 20)'
-)
-test_expect_equal "$output" '"max-length-test"'
-
-test_begin_subtest "filename #9"
-output=$(test_emacs '(notmuch-wash-subject-to-filename
- "[a prefix] [is only separated] by [spaces], so \"by\" is not okay!")'
-)
-test_expect_equal "$output" '"by-spaces-so-by-is-not-okay"'
-
-# test notmuch-wash-subject-to-patch-filename (subject)
-test_begin_subtest "patch filename #1"
-output=$(test_emacs '(notmuch-wash-subject-to-patch-filename
- "[RFC][PATCH 099/100] rewrite notmuch")'
-)
-test_expect_equal "$output" '"0099-rewrite-notmuch.patch"'
-
-test_begin_subtest "patch filename #2"
-output=$(test_emacs '(notmuch-wash-subject-to-patch-filename
- "[RFC PATCH v1] has no patch number, default to 1")'
-)
-test_expect_equal "$output" '"0001-has-no-patch-number-default-to-1.patch"'
-
-test_begin_subtest "patch filename #3"
-output=$(test_emacs '(notmuch-wash-subject-to-patch-filename
- "[PATCH 4/5] the maximum length of a patch filename is 52 + patch sequence number + .patch extension")'
-)
-test_expect_equal "$output" '"0004-the-maximum-length-of-a-patch-filename-is-52-patch-s.patch"'
-
-test_begin_subtest "patch filename #4"
-output=$(test_emacs '(notmuch-wash-subject-to-patch-filename
- "[PATCH 4/5] the maximum length of a patch filename is 52 + patchh ! sequence number + .patch extension, *before* trimming trailing - and .")'
-)
-test_expect_equal "$output" '"0004-the-maximum-length-of-a-patch-filename-is-52-patchh.patch"'
-
-test_done
+++ /dev/null
-#!/usr/bin/env bash
-
-test_description="emacs test function sanity"
-. ./test-lib.sh
-
-test_begin_subtest "emacs test function sanity"
-test_emacs_expect_t 't'
-
-test_done
+++ /dev/null
-#!/usr/bin/env bash
-
-test_description="emacs tree view interface"
-. test-lib.sh
-
-EXPECTED=$TEST_DIRECTORY/tree.expected-output
-
-add_email_corpus
-
-test_begin_subtest "Basic notmuch-tree view in emacs"
-test_emacs '(add-to-list (quote load-path) "'$PICK_DIR'")
- (notmuch-tree "tag:inbox")
- (notmuch-test-wait)
- (test-output)
- (delete-other-windows)'
-test_expect_equal_file OUTPUT $EXPECTED/notmuch-tree-tag-inbox
-
-test_begin_subtest "Refreshed notmuch-tree view in emacs"
-test_emacs '(add-to-list (quote load-path) "'$PICK_DIR'")
- (notmuch-tree "tag:inbox")
- (notmuch-test-wait)
- (notmuch-tree-refresh-view)
- (notmuch-test-wait)
- (test-output)
- (delete-other-windows)'
-test_expect_equal_file OUTPUT $EXPECTED/notmuch-tree-tag-inbox
-
-# In the following tag tests we make sure the display is updated
-# correctly and, in a separate test, that the database is updated
-# correctly.
-
-test_begin_subtest "Tag message in notmuch tree view (display)"
-test_emacs '(add-to-list (quote load-path) "'$PICK_DIR'")
- (notmuch-tree "tag:inbox")
- (notmuch-test-wait)
- (forward-line)
- (notmuch-tree-tag (list "+test_tag"))
- (test-output)
- (delete-other-windows)'
-test_expect_equal_file OUTPUT $EXPECTED/notmuch-tree-tag-inbox-tagged
-
-test_begin_subtest "Tag message in notmuch tree view (database)"
-output=$(notmuch search --output=messages 'tag:test_tag')
-test_expect_equal "$output" "id:877h1wv7mg.fsf@inf-8657.int-evry.fr"
-
-test_begin_subtest "Untag message in notmuch tree view"
-test_emacs '(add-to-list (quote load-path) "'$PICK_DIR'")
- (notmuch-tree "tag:inbox")
- (notmuch-test-wait)
- (forward-line)
- (notmuch-tree-tag (list "-test_tag"))
- (test-output)
- (delete-other-windows)'
-test_expect_equal_file OUTPUT $EXPECTED/notmuch-tree-tag-inbox
-
-test_begin_subtest "Untag message in notmuch tree view (database)"
-output=$(notmuch search --output=messages 'tag:test_tag')
-test_expect_equal "$output" ""
-
-test_begin_subtest "Tag thread in notmuch tree view"
-test_emacs '(add-to-list (quote load-path) "'$PICK_DIR'")
- (notmuch-tree "tag:inbox")
- (notmuch-test-wait)
- ;; move to a sizable thread
- (forward-line 26)
- (notmuch-tree-tag-thread (list "+test_thread_tag"))
- (test-output)
- (delete-other-windows)'
-test_expect_equal_file OUTPUT $EXPECTED/notmuch-tree-tag-inbox-thread-tagged
-
-test_begin_subtest "Tag message in notmuch tree view (database)"
-output=$(notmuch search --output=messages 'tag:test_thread_tag')
-test_expect_equal "$output" \
-"id:87ocn0qh6d.fsf@yoom.home.cworth.org
-id:20091118005040.GA25380@dottiness.seas.harvard.edu
-id:yunaayketfm.fsf@aiko.keithp.com
-id:87fx8can9z.fsf@vertex.dottedmag
-id:20091117203301.GV3165@dottiness.seas.harvard.edu
-id:87iqd9rn3l.fsf@vertex.dottedmag
-id:20091117190054.GU3165@dottiness.seas.harvard.edu"
-
-test_begin_subtest "Untag thread in notmuch tree view"
-test_emacs '(add-to-list (quote load-path) "'$PICK_DIR'")
- (notmuch-tree "tag:inbox")
- (notmuch-test-wait)
- ;; move to the same sizable thread as above
- (forward-line 26)
- (notmuch-tree-tag-thread (list "-test_thread_tag"))
- (test-output)
- (delete-other-windows)'
-test_expect_equal_file OUTPUT $EXPECTED/notmuch-tree-tag-inbox
-
-test_begin_subtest "Untag message in notmuch tree view (database)"
-output=$(notmuch search --output=messages 'tag:test_thread_tag')
-test_expect_equal "$output" ""
-
-test_begin_subtest "Navigation of notmuch-hello to search results"
-test_emacs '(notmuch-hello)
- (goto-char (point-min))
- (re-search-forward "inbox")
- (widget-button-press (1- (point)))
- (notmuch-test-wait)
- (notmuch-tree-from-search-current-query)
- (notmuch-test-wait)
- (test-output)
- (delete-other-windows)'
-test_expect_equal_file OUTPUT $EXPECTED/notmuch-tree-tag-inbox
-
-test_begin_subtest "Tree view of a single thread (from search)"
-test_emacs '(notmuch-hello)
- (goto-char (point-min))
- (re-search-forward "inbox")
- (widget-button-press (1- (point)))
- (notmuch-test-wait)
- (notmuch-tree-from-search-thread)
- (notmuch-test-wait)
- (test-output)
- (delete-other-windows)'
-test_expect_equal_file OUTPUT $EXPECTED/notmuch-tree-single-thread
-
-test_begin_subtest "Tree view of a single thread (from show)"
-test_emacs '(notmuch-hello)
- (goto-char (point-min))
- (re-search-forward "inbox")
- (widget-button-press (1- (point)))
- (notmuch-test-wait)
- (notmuch-search-show-thread)
- (notmuch-tree-from-show-current-query)
- (notmuch-test-wait)
- (test-output)
- (delete-other-windows)'
-test_expect_equal_file OUTPUT $EXPECTED/notmuch-tree-single-thread
-
-test_begin_subtest "Message window of tree view"
-test_emacs '(notmuch-hello)
- (goto-char (point-min))
- (re-search-forward "inbox")
- (widget-button-press (1- (point)))
- (notmuch-test-wait)
- (notmuch-search-next-thread)
- (notmuch-tree-from-search-thread)
- (notmuch-test-wait)
- (select-window notmuch-tree-message-window)
- (test-output)
- (delete-other-windows)'
-cp OUTPUT /tmp/mjwout
-test_expect_equal_file OUTPUT $EXPECTED/notmuch-tree-show-window
-
-test_begin_subtest "Stash id"
-output=$(test_emacs '(add-to-list (quote load-path) "'$PICK_DIR'")
- (require (quote notmuch-tree))
- (notmuch-tree "id:1258498485-sup-142@elly")
- (notmuch-test-wait)
- (notmuch-show-stash-message-id)')
-test_expect_equal "$output" "\"Stashed: id:1258498485-sup-142@elly\""
-
-test_begin_subtest "Move to next matching message"
-output=$(test_emacs '(add-to-list (quote load-path) "'$PICK_DIR'")
- (require (quote notmuch-tree))
- (notmuch-tree "from:cworth")
- (notmuch-test-wait)
- (notmuch-tree-next-matching-message)
- (notmuch-show-stash-message-id)')
-test_expect_equal "$output" "\"Stashed: id:878we4qdqf.fsf@yoom.home.cworth.org\""
-
-test_begin_subtest "Move to next thread"
-output=$(test_emacs '(add-to-list (quote load-path) "'$PICK_DIR'")
- (require (quote notmuch-tree))
- (notmuch-tree "tag:inbox")
- (notmuch-test-wait)
- (forward-line 26)
- (notmuch-tree-next-thread)
- (notmuch-show-stash-message-id)')
-test_expect_equal "$output" "\"Stashed: id:1258471718-6781-1-git-send-email-dottedmag@dottedmag.net\""
-
-test_begin_subtest "Move to previous thread"
-output=$(test_emacs '(add-to-list (quote load-path) "'$PICK_DIR'")
- (require (quote notmuch-tree))
- (notmuch-tree "tag:inbox")
- (notmuch-test-wait)
- (forward-line 26)
- (notmuch-tree-prev-thread)
- (notmuch-show-stash-message-id)')
-test_expect_equal "$output" "\"Stashed: id:20091117190054.GU3165@dottiness.seas.harvard.edu\""
-
-test_begin_subtest "Move to previous previous thread"
-output=$(test_emacs '(add-to-list (quote load-path) "'$PICK_DIR'")
- (require (quote notmuch-tree))
- (notmuch-tree "tag:inbox")
- (notmuch-test-wait)
- (forward-line 26)
- (notmuch-tree-prev-thread)
- (notmuch-tree-prev-thread)
- (notmuch-show-stash-message-id)')
-test_expect_equal "$output" "\"Stashed: id:1258493565-13508-1-git-send-email-keithp@keithp.com\""
-
-test_done
+++ /dev/null
-#!/usr/bin/env bash
-test_description="encoding issues"
-. ./test-lib.sh
-
-test_begin_subtest "Message with text of unknown charset"
-add_message '[content-type]="text/plain; charset=unknown-8bit"' \
- "[body]=irrelevant"
-output=$(notmuch show id:${gen_msg_id} 2>&1 | notmuch_show_sanitize_all)
-test_expect_equal "$output" "\fmessage{ id:XXXXX depth:0 match:1 excluded:0 filename:XXXXX
-\fheader{
-Notmuch Test Suite <test_suite@notmuchmail.org> (2001-01-05) (inbox unread)
-Subject: Message with text of unknown charset
-From: Notmuch Test Suite <test_suite@notmuchmail.org>
-To: Notmuch Test Suite <test_suite@notmuchmail.org>
-Date: GENERATED_DATE
-\fheader}
-\fbody{
-\fpart{ ID: 1, Content-type: text/plain
-irrelevant
-\fpart}
-\fbody}
-\fmessage}"
-
-test_begin_subtest "Search for ISO-8859-2 encoded message"
-add_message '[content-type]="text/plain; charset=iso-8859-2"' \
- '[content-transfer-encoding]=8bit' \
- '[subject]="ISO-8859-2 encoded message"' \
- "[body]=$'Czech word tu\350\362\341\350\350\355 means pinguin\'s.'" # ISO-8859-2 characters are generated by shell's escape sequences
-output=$(notmuch search tučňáččí 2>&1 | notmuch_show_sanitize_all)
-test_expect_equal "$output" "thread:0000000000000002 2001-01-05 [1/1] Notmuch Test Suite; ISO-8859-2 encoded message (inbox unread)"
-
-test_begin_subtest "RFC 2047 encoded word with spaces"
-add_message '[subject]="=?utf-8?q?encoded word with spaces?="'
-output=$(notmuch search id:${gen_msg_id} 2>&1 | notmuch_show_sanitize)
-test_expect_equal "$output" "thread:0000000000000003 2001-01-05 [1/1] Notmuch Test Suite; encoded word with spaces (inbox unread)"
-
-test_begin_subtest "RFC 2047 encoded words back to back"
-add_message '[subject]="=?utf-8?q?encoded-words-back?==?utf-8?q?to-back?="'
-output=$(notmuch search id:${gen_msg_id} 2>&1 | notmuch_show_sanitize)
-test_expect_equal "$output" "thread:0000000000000004 2001-01-05 [1/1] Notmuch Test Suite; encoded-words-backto-back (inbox unread)"
-
-test_begin_subtest "RFC 2047 encoded words without space before or after"
-add_message '[subject]="=?utf-8?q?encoded?=word without=?utf-8?q?space?=" '
-output=$(notmuch search id:${gen_msg_id} 2>&1 | notmuch_show_sanitize)
-test_expect_equal "$output" "thread:0000000000000005 2001-01-05 [1/1] Notmuch Test Suite; encodedword withoutspace (inbox unread)"
-
-test_done
+++ /dev/null
-#!/usr/bin/env bash
-test_description='"notmuch search, count and show" with excludes in several variations'
-. ./test-lib.sh
-
-# Generates a thread consisting of a top level message and 'length'
-# replies. The subject of the top message 'subject: top message"
-# and the subject of the nth reply in the thread is "subject: reply n"
-generate_thread ()
-{
- local subject="$1"
- local length="$2"
- generate_message '[subject]="'"${subject}: top message"'"' '[body]="'"body of top message"'"'
- parent_id=$gen_msg_id
- gen_thread_msg_id[0]=$gen_msg_id
- for i in `seq 1 $length`
- do
- generate_message '[subject]="'"${subject}: reply $i"'"' \
- "[in-reply-to]=\<$parent_id\>" \
- '[body]="'"body of reply $i"'"'
- gen_thread_msg_id[$i]=$gen_msg_id
- parent_id=$gen_msg_id
- done
- notmuch new > /dev/null
- # We cannot retrieve the thread_id until after we have run notmuch new.
- gen_thread_id=`notmuch search --output=threads id:${gen_thread_msg_id[0]}`
-}
-
-#############################################
-# These are the original search exclude tests.
-
-test_begin_subtest "Search, exclude \"deleted\" messages from search"
-notmuch config set search.exclude_tags deleted
-generate_message '[subject]="Not deleted"'
-not_deleted_id=$gen_msg_id
-generate_message '[subject]="Deleted"'
-notmuch new > /dev/null
-notmuch tag +deleted id:$gen_msg_id
-deleted_id=$gen_msg_id
-output=$(notmuch search subject:deleted | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Not deleted (inbox unread)"
-
-test_begin_subtest "Search, exclude \"deleted\" messages from message search"
-output=$(notmuch search --output=messages subject:deleted | notmuch_search_sanitize)
-test_expect_equal "$output" "id:$not_deleted_id"
-
-test_begin_subtest "Search, exclude \"deleted\" messages from message search --exclude=false"
-output=$(notmuch search --exclude=false --output=messages subject:deleted | notmuch_search_sanitize)
-test_expect_equal "$output" "id:$not_deleted_id
-id:$deleted_id"
-
-test_begin_subtest "Search, exclude \"deleted\" messages from message search (non-existent exclude-tag)"
-notmuch config set search.exclude_tags deleted non_existent_tag
-output=$(notmuch search --output=messages subject:deleted | notmuch_search_sanitize)
-test_expect_equal "$output" "id:$not_deleted_id"
-notmuch config set search.exclude_tags deleted
-
-test_begin_subtest "Search, exclude \"deleted\" messages from search, overridden"
-output=$(notmuch search subject:deleted and tag:deleted | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Deleted (deleted inbox unread)"
-
-test_begin_subtest "Search, exclude \"deleted\" messages from threads"
-add_message '[subject]="Not deleted reply"' '[in-reply-to]="<$gen_msg_id>"'
-output=$(notmuch search subject:deleted | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Not deleted (inbox unread)
-thread:XXX 2001-01-05 [1/2] Notmuch Test Suite; Not deleted reply (deleted inbox unread)"
-
-test_begin_subtest "Search, don't exclude \"deleted\" messages when --exclude=flag specified"
-output=$(notmuch search --exclude=flag subject:deleted | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Not deleted (inbox unread)
-thread:XXX 2001-01-05 [1/2] Notmuch Test Suite; Deleted (deleted inbox unread)"
-
-test_begin_subtest "Search, don't exclude \"deleted\" messages from search if not configured"
-notmuch config set search.exclude_tags
-output=$(notmuch search subject:deleted | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Not deleted (inbox unread)
-thread:XXX 2001-01-05 [2/2] Notmuch Test Suite; Deleted (deleted inbox unread)"
-
-
-########################################################
-# We construct some threads for the tests. We use the tag "test" to
-# indicate which messages we will search for.
-
-# A thread of deleted messages; test matches one of them.
-generate_thread "All messages excluded: single match" 5
-notmuch tag +deleted $gen_thread_id
-notmuch tag +test id:${gen_thread_msg_id[2]}
-
-# A thread of deleted messages; test matches two of them.
-generate_thread "All messages excluded: double match" 5
-notmuch tag +deleted $gen_thread_id
-notmuch tag +test id:${gen_thread_msg_id[2]}
-notmuch tag +test id:${gen_thread_msg_id[4]}
-
-# A thread some messages deleted; test only matches a deleted message.
-generate_thread "Some messages excluded: single excluded match" 5
-notmuch tag +deleted +test id:${gen_thread_msg_id[3]}
-
-# A thread some messages deleted; test only matches a non-deleted message.
-generate_thread "Some messages excluded: single non-excluded match" 5
-notmuch tag +deleted id:${gen_thread_msg_id[2]}
-notmuch tag +test id:${gen_thread_msg_id[4]}
-
-# A thread no messages deleted; test matches a message.
-generate_thread "No messages excluded: single match" 5
-notmuch tag +test id:${gen_thread_msg_id[3]}
-
-# Temporarily remove excludes to get list of matching messages
-notmuch config set search.exclude_tags
-matching_message_ids=( `notmuch search --output=messages tag:test` )
-notmuch config set search.exclude_tags deleted
-
-#########################################
-# Notmuch search tests
-
-test_begin_subtest "Search, default exclusion (thread summary)"
-output=$(notmuch search tag:test | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2001-01-05 [1/6] Notmuch Test Suite; Some messages excluded: single non-excluded match: reply 4 (deleted inbox test unread)
-thread:XXX 2001-01-05 [1/6] Notmuch Test Suite; No messages excluded: single match: reply 3 (inbox test unread)"
-
-test_begin_subtest "Search, default exclusion (messages)"
-output=$(notmuch search --output=messages tag:test | notmuch_search_sanitize)
-test_expect_equal "$output" "${matching_message_ids[4]}
-${matching_message_ids[5]}"
-
-test_begin_subtest "Search, exclude=true (thread summary)"
-output=$(notmuch search --exclude=true tag:test | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2001-01-05 [1/6] Notmuch Test Suite; Some messages excluded: single non-excluded match: reply 4 (deleted inbox test unread)
-thread:XXX 2001-01-05 [1/6] Notmuch Test Suite; No messages excluded: single match: reply 3 (inbox test unread)"
-
-test_begin_subtest "Search, exclude=true (messages)"
-output=$(notmuch search --exclude=true --output=messages tag:test | notmuch_search_sanitize)
-test_expect_equal "$output" "${matching_message_ids[4]}
-${matching_message_ids[5]}"
-
-test_begin_subtest "Search, exclude=false (thread summary)"
-output=$(notmuch search --exclude=false tag:test | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2001-01-05 [1/6] Notmuch Test Suite; All messages excluded: single match: reply 2 (deleted inbox test unread)
-thread:XXX 2001-01-05 [2/6] Notmuch Test Suite; All messages excluded: double match: reply 2 (deleted inbox test unread)
-thread:XXX 2001-01-05 [1/6] Notmuch Test Suite; Some messages excluded: single excluded match: reply 3 (deleted inbox test unread)
-thread:XXX 2001-01-05 [1/6] Notmuch Test Suite; Some messages excluded: single non-excluded match: reply 4 (deleted inbox test unread)
-thread:XXX 2001-01-05 [1/6] Notmuch Test Suite; No messages excluded: single match: reply 3 (inbox test unread)"
-
-test_begin_subtest "Search, exclude=false (messages)"
-output=$(notmuch search --exclude=false --output=messages tag:test | notmuch_search_sanitize)
-test_expect_equal "$output" "${matching_message_ids[0]}
-${matching_message_ids[1]}
-${matching_message_ids[2]}
-${matching_message_ids[3]}
-${matching_message_ids[4]}
-${matching_message_ids[5]}"
-
-test_begin_subtest "Search, exclude=flag (thread summary)"
-output=$(notmuch search --exclude=flag tag:test | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2001-01-05 [0/6] Notmuch Test Suite; All messages excluded: single match: reply 2 (deleted inbox test unread)
-thread:XXX 2001-01-05 [0/6] Notmuch Test Suite; All messages excluded: double match: reply 2 (deleted inbox test unread)
-thread:XXX 2001-01-05 [0/6] Notmuch Test Suite; Some messages excluded: single excluded match: reply 3 (deleted inbox test unread)
-thread:XXX 2001-01-05 [1/6] Notmuch Test Suite; Some messages excluded: single non-excluded match: reply 4 (deleted inbox test unread)
-thread:XXX 2001-01-05 [1/6] Notmuch Test Suite; No messages excluded: single match: reply 3 (inbox test unread)"
-
-test_begin_subtest "Search, exclude=flag (messages)"
-output=$(notmuch search --exclude=flag --output=messages tag:test | notmuch_search_sanitize)
-test_expect_equal "$output" "${matching_message_ids[0]}
-${matching_message_ids[1]}
-${matching_message_ids[2]}
-${matching_message_ids[3]}
-${matching_message_ids[4]}
-${matching_message_ids[5]}"
-
-test_begin_subtest "Search, exclude=all (thread summary)"
-output=$(notmuch search --exclude=all tag:test | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2001-01-05 [1/5] Notmuch Test Suite; Some messages excluded: single non-excluded match: reply 4 (inbox test unread)
-thread:XXX 2001-01-05 [1/6] Notmuch Test Suite; No messages excluded: single match: reply 3 (inbox test unread)"
-
-test_begin_subtest "Search, exclude=all (messages)"
-output=$(notmuch search --exclude=all --output=messages tag:test | notmuch_search_sanitize)
-test_expect_equal "$output" "${matching_message_ids[4]}
-${matching_message_ids[5]}"
-
-test_begin_subtest "Search, default exclusion: tag in query (thread summary)"
-output=$(notmuch search tag:test and tag:deleted | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2001-01-05 [1/6] Notmuch Test Suite; All messages excluded: single match: reply 2 (deleted inbox test unread)
-thread:XXX 2001-01-05 [2/6] Notmuch Test Suite; All messages excluded: double match: reply 2 (deleted inbox test unread)
-thread:XXX 2001-01-05 [1/6] Notmuch Test Suite; Some messages excluded: single excluded match: reply 3 (deleted inbox test unread)"
-
-test_begin_subtest "Search, default exclusion: tag in query (messages)"
-output=$(notmuch search --output=messages tag:test and tag:deleted | notmuch_search_sanitize)
-test_expect_equal "$output" "${matching_message_ids[0]}
-${matching_message_ids[1]}
-${matching_message_ids[2]}
-${matching_message_ids[3]}"
-
-test_begin_subtest "Search, exclude=true: tag in query (thread summary)"
-output=$(notmuch search --exclude=true tag:test and tag:deleted | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2001-01-05 [1/6] Notmuch Test Suite; All messages excluded: single match: reply 2 (deleted inbox test unread)
-thread:XXX 2001-01-05 [2/6] Notmuch Test Suite; All messages excluded: double match: reply 2 (deleted inbox test unread)
-thread:XXX 2001-01-05 [1/6] Notmuch Test Suite; Some messages excluded: single excluded match: reply 3 (deleted inbox test unread)"
-
-test_begin_subtest "Search, exclude=true: tag in query (messages)"
-output=$(notmuch search --exclude=true --output=messages tag:test and tag:deleted | notmuch_search_sanitize)
-test_expect_equal "$output" "${matching_message_ids[0]}
-${matching_message_ids[1]}
-${matching_message_ids[2]}
-${matching_message_ids[3]}"
-
-test_begin_subtest "Search, exclude=false: tag in query (thread summary)"
-output=$(notmuch search --exclude=false tag:test and tag:deleted | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2001-01-05 [1/6] Notmuch Test Suite; All messages excluded: single match: reply 2 (deleted inbox test unread)
-thread:XXX 2001-01-05 [2/6] Notmuch Test Suite; All messages excluded: double match: reply 2 (deleted inbox test unread)
-thread:XXX 2001-01-05 [1/6] Notmuch Test Suite; Some messages excluded: single excluded match: reply 3 (deleted inbox test unread)"
-
-test_begin_subtest "Search, exclude=false: tag in query (messages)"
-output=$(notmuch search --exclude=false --output=messages tag:test and tag:deleted | notmuch_search_sanitize)
-test_expect_equal "$output" "${matching_message_ids[0]}
-${matching_message_ids[1]}
-${matching_message_ids[2]}
-${matching_message_ids[3]}"
-
-test_begin_subtest "Search, exclude=flag: tag in query (thread summary)"
-output=$(notmuch search --exclude=flag tag:test and tag:deleted | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2001-01-05 [1/6] Notmuch Test Suite; All messages excluded: single match: reply 2 (deleted inbox test unread)
-thread:XXX 2001-01-05 [2/6] Notmuch Test Suite; All messages excluded: double match: reply 2 (deleted inbox test unread)
-thread:XXX 2001-01-05 [1/6] Notmuch Test Suite; Some messages excluded: single excluded match: reply 3 (deleted inbox test unread)"
-
-test_begin_subtest "Search, exclude=flag: tag in query (messages)"
-output=$(notmuch search --exclude=flag --output=messages tag:test and tag:deleted | notmuch_search_sanitize)
-test_expect_equal "$output" "${matching_message_ids[0]}
-${matching_message_ids[1]}
-${matching_message_ids[2]}
-${matching_message_ids[3]}"
-
-test_begin_subtest "Search, exclude=all: tag in query (thread summary)"
-output=$(notmuch search --exclude=all tag:test and tag:deleted | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2001-01-05 [1/6] Notmuch Test Suite; All messages excluded: single match: reply 2 (deleted inbox test unread)
-thread:XXX 2001-01-05 [2/6] Notmuch Test Suite; All messages excluded: double match: reply 2 (deleted inbox test unread)
-thread:XXX 2001-01-05 [1/6] Notmuch Test Suite; Some messages excluded: single excluded match: reply 3 (deleted inbox test unread)"
-
-test_begin_subtest "Search, exclude=all: tag in query (messages)"
-output=$(notmuch search --exclude=all --output=messages tag:test and tag:deleted | notmuch_search_sanitize)
-test_expect_equal "$output" "${matching_message_ids[0]}
-${matching_message_ids[1]}
-${matching_message_ids[2]}
-${matching_message_ids[3]}"
-
-#########################################################
-# Notmuch count tests
-
-test_begin_subtest "Count, default exclusion (messages)"
-output=$(notmuch count tag:test)
-test_expect_equal "$output" "2"
-
-test_begin_subtest "Count, default exclusion (threads)"
-output=$(notmuch count --output=threads tag:test)
-test_expect_equal "$output" "2"
-
-test_begin_subtest "Count, exclude=true (messages)"
-output=$(notmuch count --exclude=true tag:test)
-test_expect_equal "$output" "2"
-
-test_begin_subtest "Count, exclude=true (threads)"
-output=$(notmuch count --output=threads --exclude=true tag:test)
-test_expect_equal "$output" "2"
-
-test_begin_subtest "Count, exclude=false (messages)"
-output=$(notmuch count --exclude=false tag:test)
-test_expect_equal "$output" "6"
-
-test_begin_subtest "Count, exclude=false (threads)"
-output=$(notmuch count --output=threads --exclude=false tag:test)
-test_expect_equal "$output" "5"
-
-test_begin_subtest "Count, default exclusion: tag in query (messages)"
-output=$(notmuch count tag:test and tag:deleted)
-test_expect_equal "$output" "4"
-
-test_begin_subtest "Count, default exclusion: tag in query (threads)"
-output=$(notmuch count --output=threads tag:test and tag:deleted)
-test_expect_equal "$output" "3"
-
-test_begin_subtest "Count, exclude=true: tag in query (messages)"
-output=$(notmuch count --exclude=true tag:test and tag:deleted)
-test_expect_equal "$output" "4"
-
-test_begin_subtest "Count, exclude=true: tag in query (threads)"
-output=$(notmuch count --output=threads --exclude=true tag:test and tag:deleted)
-test_expect_equal "$output" "3"
-
-test_begin_subtest "Count, exclude=false: tag in query (messages)"
-output=$(notmuch count --exclude=false tag:test and tag:deleted)
-test_expect_equal "$output" "4"
-
-test_begin_subtest "Count, exclude=false: tag in query (threads)"
-output=$(notmuch count --output=threads --exclude=false tag:test and tag:deleted)
-test_expect_equal "$output" "3"
-
-#############################################################
-# Show tests
-
-test_begin_subtest "Show, default exclusion"
-output=$(notmuch show tag:test | notmuch_show_sanitize_all | egrep "Subject:|message{")
-test_expect_equal "$output" "\fmessage{ id:XXXXX depth:0 match:1 excluded:0 filename:XXXXX
-Subject: Some messages excluded: single non-excluded match: reply 4
-\fmessage{ id:XXXXX depth:0 match:1 excluded:0 filename:XXXXX
-Subject: No messages excluded: single match: reply 3"
-
-test_begin_subtest "Show, default exclusion (entire-thread)"
-output=$(notmuch show --entire-thread tag:test | notmuch_show_sanitize_all | egrep "Subject:|message{")
-test_expect_equal "$output" "\fmessage{ id:XXXXX depth:0 match:0 excluded:0 filename:XXXXX
-Subject: Some messages excluded: single non-excluded match: top message
-\fmessage{ id:XXXXX depth:1 match:0 excluded:0 filename:XXXXX
-Subject: Some messages excluded: single non-excluded match: reply 1
-\fmessage{ id:XXXXX depth:2 match:0 excluded:1 filename:XXXXX
-Subject: Some messages excluded: single non-excluded match: reply 2
-\fmessage{ id:XXXXX depth:3 match:0 excluded:0 filename:XXXXX
-Subject: Some messages excluded: single non-excluded match: reply 3
-\fmessage{ id:XXXXX depth:4 match:1 excluded:0 filename:XXXXX
-Subject: Some messages excluded: single non-excluded match: reply 4
-\fmessage{ id:XXXXX depth:5 match:0 excluded:0 filename:XXXXX
-Subject: Some messages excluded: single non-excluded match: reply 5
-\fmessage{ id:XXXXX depth:0 match:0 excluded:0 filename:XXXXX
-Subject: No messages excluded: single match: top message
-\fmessage{ id:XXXXX depth:1 match:0 excluded:0 filename:XXXXX
-Subject: No messages excluded: single match: reply 1
-\fmessage{ id:XXXXX depth:2 match:0 excluded:0 filename:XXXXX
-Subject: No messages excluded: single match: reply 2
-\fmessage{ id:XXXXX depth:3 match:1 excluded:0 filename:XXXXX
-Subject: No messages excluded: single match: reply 3
-\fmessage{ id:XXXXX depth:4 match:0 excluded:0 filename:XXXXX
-Subject: No messages excluded: single match: reply 4
-\fmessage{ id:XXXXX depth:5 match:0 excluded:0 filename:XXXXX
-Subject: No messages excluded: single match: reply 5"
-
-test_begin_subtest "Show, exclude=true"
-output=$(notmuch show --exclude=true tag:test | notmuch_show_sanitize_all | egrep "Subject:|message{")
-test_expect_equal "$output" "\fmessage{ id:XXXXX depth:0 match:1 excluded:0 filename:XXXXX
-Subject: Some messages excluded: single non-excluded match: reply 4
-\fmessage{ id:XXXXX depth:0 match:1 excluded:0 filename:XXXXX
-Subject: No messages excluded: single match: reply 3"
-
-test_begin_subtest "Show, exclude=true (entire-thread)"
-output=$(notmuch show --entire-thread --exclude=true tag:test | notmuch_show_sanitize_all | egrep "Subject:|message{")
-test_expect_equal "$output" "\fmessage{ id:XXXXX depth:0 match:0 excluded:0 filename:XXXXX
-Subject: Some messages excluded: single non-excluded match: top message
-\fmessage{ id:XXXXX depth:1 match:0 excluded:0 filename:XXXXX
-Subject: Some messages excluded: single non-excluded match: reply 1
-\fmessage{ id:XXXXX depth:2 match:0 excluded:1 filename:XXXXX
-Subject: Some messages excluded: single non-excluded match: reply 2
-\fmessage{ id:XXXXX depth:3 match:0 excluded:0 filename:XXXXX
-Subject: Some messages excluded: single non-excluded match: reply 3
-\fmessage{ id:XXXXX depth:4 match:1 excluded:0 filename:XXXXX
-Subject: Some messages excluded: single non-excluded match: reply 4
-\fmessage{ id:XXXXX depth:5 match:0 excluded:0 filename:XXXXX
-Subject: Some messages excluded: single non-excluded match: reply 5
-\fmessage{ id:XXXXX depth:0 match:0 excluded:0 filename:XXXXX
-Subject: No messages excluded: single match: top message
-\fmessage{ id:XXXXX depth:1 match:0 excluded:0 filename:XXXXX
-Subject: No messages excluded: single match: reply 1
-\fmessage{ id:XXXXX depth:2 match:0 excluded:0 filename:XXXXX
-Subject: No messages excluded: single match: reply 2
-\fmessage{ id:XXXXX depth:3 match:1 excluded:0 filename:XXXXX
-Subject: No messages excluded: single match: reply 3
-\fmessage{ id:XXXXX depth:4 match:0 excluded:0 filename:XXXXX
-Subject: No messages excluded: single match: reply 4
-\fmessage{ id:XXXXX depth:5 match:0 excluded:0 filename:XXXXX
-Subject: No messages excluded: single match: reply 5"
-
-test_begin_subtest "Show, exclude=false"
-output=$(notmuch show --exclude=false tag:test | notmuch_show_sanitize_all | egrep "Subject:|message{")
-test_expect_equal "$output" "\fmessage{ id:XXXXX depth:0 match:1 excluded:1 filename:XXXXX
-Subject: All messages excluded: single match: reply 2
-\fmessage{ id:XXXXX depth:0 match:1 excluded:1 filename:XXXXX
-Subject: All messages excluded: double match: reply 2
-\fmessage{ id:XXXXX depth:1 match:1 excluded:1 filename:XXXXX
-Subject: All messages excluded: double match: reply 4
-\fmessage{ id:XXXXX depth:0 match:1 excluded:1 filename:XXXXX
-Subject: Some messages excluded: single excluded match: reply 3
-\fmessage{ id:XXXXX depth:0 match:1 excluded:0 filename:XXXXX
-Subject: Some messages excluded: single non-excluded match: reply 4
-\fmessage{ id:XXXXX depth:0 match:1 excluded:0 filename:XXXXX
-Subject: No messages excluded: single match: reply 3"
-
-test_begin_subtest "Show, exclude=false (entire-thread)"
-output=$(notmuch show --entire-thread --exclude=false tag:test | notmuch_show_sanitize_all | egrep "Subject:|message{")
-test_expect_equal "$output" "\fmessage{ id:XXXXX depth:0 match:0 excluded:1 filename:XXXXX
-Subject: All messages excluded: single match: top message
-\fmessage{ id:XXXXX depth:1 match:0 excluded:1 filename:XXXXX
-Subject: All messages excluded: single match: reply 1
-\fmessage{ id:XXXXX depth:2 match:1 excluded:1 filename:XXXXX
-Subject: All messages excluded: single match: reply 2
-\fmessage{ id:XXXXX depth:3 match:0 excluded:1 filename:XXXXX
-Subject: All messages excluded: single match: reply 3
-\fmessage{ id:XXXXX depth:4 match:0 excluded:1 filename:XXXXX
-Subject: All messages excluded: single match: reply 4
-\fmessage{ id:XXXXX depth:5 match:0 excluded:1 filename:XXXXX
-Subject: All messages excluded: single match: reply 5
-\fmessage{ id:XXXXX depth:0 match:0 excluded:1 filename:XXXXX
-Subject: All messages excluded: double match: top message
-\fmessage{ id:XXXXX depth:1 match:0 excluded:1 filename:XXXXX
-Subject: All messages excluded: double match: reply 1
-\fmessage{ id:XXXXX depth:2 match:1 excluded:1 filename:XXXXX
-Subject: All messages excluded: double match: reply 2
-\fmessage{ id:XXXXX depth:3 match:0 excluded:1 filename:XXXXX
-Subject: All messages excluded: double match: reply 3
-\fmessage{ id:XXXXX depth:4 match:1 excluded:1 filename:XXXXX
-Subject: All messages excluded: double match: reply 4
-\fmessage{ id:XXXXX depth:5 match:0 excluded:1 filename:XXXXX
-Subject: All messages excluded: double match: reply 5
-\fmessage{ id:XXXXX depth:0 match:0 excluded:0 filename:XXXXX
-Subject: Some messages excluded: single excluded match: top message
-\fmessage{ id:XXXXX depth:1 match:0 excluded:0 filename:XXXXX
-Subject: Some messages excluded: single excluded match: reply 1
-\fmessage{ id:XXXXX depth:2 match:0 excluded:0 filename:XXXXX
-Subject: Some messages excluded: single excluded match: reply 2
-\fmessage{ id:XXXXX depth:3 match:1 excluded:1 filename:XXXXX
-Subject: Some messages excluded: single excluded match: reply 3
-\fmessage{ id:XXXXX depth:4 match:0 excluded:0 filename:XXXXX
-Subject: Some messages excluded: single excluded match: reply 4
-\fmessage{ id:XXXXX depth:5 match:0 excluded:0 filename:XXXXX
-Subject: Some messages excluded: single excluded match: reply 5
-\fmessage{ id:XXXXX depth:0 match:0 excluded:0 filename:XXXXX
-Subject: Some messages excluded: single non-excluded match: top message
-\fmessage{ id:XXXXX depth:1 match:0 excluded:0 filename:XXXXX
-Subject: Some messages excluded: single non-excluded match: reply 1
-\fmessage{ id:XXXXX depth:2 match:0 excluded:1 filename:XXXXX
-Subject: Some messages excluded: single non-excluded match: reply 2
-\fmessage{ id:XXXXX depth:3 match:0 excluded:0 filename:XXXXX
-Subject: Some messages excluded: single non-excluded match: reply 3
-\fmessage{ id:XXXXX depth:4 match:1 excluded:0 filename:XXXXX
-Subject: Some messages excluded: single non-excluded match: reply 4
-\fmessage{ id:XXXXX depth:5 match:0 excluded:0 filename:XXXXX
-Subject: Some messages excluded: single non-excluded match: reply 5
-\fmessage{ id:XXXXX depth:0 match:0 excluded:0 filename:XXXXX
-Subject: No messages excluded: single match: top message
-\fmessage{ id:XXXXX depth:1 match:0 excluded:0 filename:XXXXX
-Subject: No messages excluded: single match: reply 1
-\fmessage{ id:XXXXX depth:2 match:0 excluded:0 filename:XXXXX
-Subject: No messages excluded: single match: reply 2
-\fmessage{ id:XXXXX depth:3 match:1 excluded:0 filename:XXXXX
-Subject: No messages excluded: single match: reply 3
-\fmessage{ id:XXXXX depth:4 match:0 excluded:0 filename:XXXXX
-Subject: No messages excluded: single match: reply 4
-\fmessage{ id:XXXXX depth:5 match:0 excluded:0 filename:XXXXX
-Subject: No messages excluded: single match: reply 5"
-
-
-test_done
+++ /dev/null
-#!/usr/bin/env bash
-test_description="From line heuristics (with multiple configured addresses)"
-. ./test-lib.sh
-
-test_begin_subtest "Magic from guessing (nothing to go on)"
-add_message '[from]="Sender <sender@example.com>"' \
- [to]=mailinglist@notmuchmail.org \
- [subject]=notmuch-reply-test \
- '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
- '[body]="from guessing test"'
-
-output=$(notmuch reply id:${gen_msg_id})
-test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@notmuchmail.org>
-Subject: Re: notmuch-reply-test
-To: Sender <sender@example.com>, mailinglist@notmuchmail.org
-In-Reply-To: <${gen_msg_id}>
-References: <${gen_msg_id}>
-
-On Tue, 05 Jan 2010 15:43:56 -0000, Sender <sender@example.com> wrote:
-> from guessing test"
-
-test_begin_subtest "Magic from guessing (Envelope-to:)"
-add_message '[from]="Sender <sender@example.com>"' \
- [to]=mailinglist@notmuchmail.org \
- [subject]=notmuch-reply-test \
- '[header]="Envelope-To: test_suite_other@notmuchmail.org"' \
- '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
- '[body]="from guessing test"'
-
-output=$(notmuch reply id:${gen_msg_id})
-test_expect_equal "$output" "From: Notmuch Test Suite <test_suite_other@notmuchmail.org>
-Subject: Re: notmuch-reply-test
-To: Sender <sender@example.com>, mailinglist@notmuchmail.org
-In-Reply-To: <${gen_msg_id}>
-References: <${gen_msg_id}>
-
-On Tue, 05 Jan 2010 15:43:56 -0000, Sender <sender@example.com> wrote:
-> from guessing test"
-
-test_begin_subtest "Magic from guessing (X-Original-To:)"
-add_message '[from]="Sender <sender@example.com>"' \
- [to]=mailinglist@notmuchmail.org \
- [subject]=notmuch-reply-test \
- '[header]="X-Original-To: test_suite_other@notmuchmail.org"' \
- '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
- '[body]="from guessing test"'
-
-output=$(notmuch reply id:${gen_msg_id})
-test_expect_equal "$output" "From: Notmuch Test Suite <test_suite_other@notmuchmail.org>
-Subject: Re: notmuch-reply-test
-To: Sender <sender@example.com>, mailinglist@notmuchmail.org
-In-Reply-To: <${gen_msg_id}>
-References: <${gen_msg_id}>
-
-On Tue, 05 Jan 2010 15:43:56 -0000, Sender <sender@example.com> wrote:
-> from guessing test"
-
-test_begin_subtest "Magic from guessing (Received: .. for ..)"
-add_message '[from]="Sender <sender@example.com>"' \
- [to]=mailinglist@notmuchmail.org \
- [subject]=notmuch-reply-test \
- "[header]=\"Received: from mail.example.com (mail.example.com [1.1.1.1])
- by mail.notmuchmail.org (some MTA) with ESMTP id 12345678
- for <test_suite_other@notmuchmail.org>; Sat, 10 Apr 2010 07:54:51 -0400 (EDT)\"" \
- '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
- '[body]="from guessing test"'
-
-output=$(notmuch reply id:${gen_msg_id})
-test_expect_equal "$output" "From: Notmuch Test Suite <test_suite_other@notmuchmail.org>
-Subject: Re: notmuch-reply-test
-To: Sender <sender@example.com>, mailinglist@notmuchmail.org
-In-Reply-To: <${gen_msg_id}>
-References: <${gen_msg_id}>
-
-On Tue, 05 Jan 2010 15:43:56 -0000, Sender <sender@example.com> wrote:
-> from guessing test"
-
-test_begin_subtest "Magic from guessing (Received: domain)"
-add_message '[from]="Sender <sender@example.com>"' \
- [to]=mailinglist@notmuchmail.org \
- [subject]=notmuch-reply-test \
- "[header]=\"Received: from mail.example.com (mail.example.com [1.1.1.1])
- by mail.otherdomain.org (some MTA) with ESMTP id 12345678
- Sat, 10 Apr 2010 07:54:51 -0400 (EDT)\"" \
- '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
- '[body]="from guessing test"'
-
-output=$(notmuch reply id:${gen_msg_id})
-test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@otherdomain.org>
-Subject: Re: notmuch-reply-test
-To: Sender <sender@example.com>, mailinglist@notmuchmail.org
-In-Reply-To: <${gen_msg_id}>
-References: <${gen_msg_id}>
-
-On Tue, 05 Jan 2010 15:43:56 -0000, Sender <sender@example.com> wrote:
-> from guessing test"
-
-test_begin_subtest "Magic from guessing (multiple Received: headers)"
-add_message '[from]="Sender <sender@example.com>"' \
- [to]=mailinglist@notmuchmail.org \
- [subject]=notmuch-reply-test \
- "[header]=\"Received: from extraneous.example.com (extraneous.example.com [1.1.1.1])
-Received: from mail.example.com (mail.example.com [1.1.1.1])
- by mail.otherdomain.org (some MTA) with ESMTP id 12345678
- for <test_suite_other@notmuchmail.org>; Sat, 10 Apr 2010 07:54:51 -0400 (EDT)
-Received: from extraneous.example.com (extraneous.example.com [1.1.1.1])\"" \
- '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
- '[body]="from guessing test"'
-
-output="$(notmuch reply id:${gen_msg_id})"
-test_expect_equal "$output" "From: Notmuch Test Suite <test_suite_other@notmuchmail.org>
-Subject: Re: notmuch-reply-test
-To: Sender <sender@example.com>, mailinglist@notmuchmail.org
-In-Reply-To: <${gen_msg_id}>
-References: <${gen_msg_id}>
-
-On Tue, 05 Jan 2010 15:43:56 -0000, Sender <sender@example.com> wrote:
-> from guessing test"
-
-test_begin_subtest "Testing From line heuristics (with single configured address)"
-sed -i -e "s/^other_email.*//" "${NOTMUCH_CONFIG}"
-test_expect_equal '' ''
-
-test_begin_subtest "Magic from guessing (nothing to go on)"
-add_message '[from]="Sender <sender@example.com>"' \
- [to]=mailinglist@notmuchmail.org \
- [subject]=notmuch-reply-test \
- '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
- '[body]="from guessing test"'
-
-output=$(notmuch reply id:${gen_msg_id})
-test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@notmuchmail.org>
-Subject: Re: notmuch-reply-test
-To: Sender <sender@example.com>, mailinglist@notmuchmail.org
-In-Reply-To: <${gen_msg_id}>
-References: <${gen_msg_id}>
-
-On Tue, 05 Jan 2010 15:43:56 -0000, Sender <sender@example.com> wrote:
-> from guessing test"
-
-test_begin_subtest "Magic from guessing (Envelope-to:)"
-add_message '[from]="Sender <sender@example.com>"' \
- [to]=mailinglist@notmuchmail.org \
- [subject]=notmuch-reply-test \
- '[header]="Envelope-To: test_suite_other@notmuchmail.org"' \
- '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
- '[body]="from guessing test"'
-
-output=$(notmuch reply id:${gen_msg_id})
-test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@notmuchmail.org>
-Subject: Re: notmuch-reply-test
-To: Sender <sender@example.com>, mailinglist@notmuchmail.org
-In-Reply-To: <${gen_msg_id}>
-References: <${gen_msg_id}>
-
-On Tue, 05 Jan 2010 15:43:56 -0000, Sender <sender@example.com> wrote:
-> from guessing test"
-
-test_begin_subtest "Magic from guessing (X-Original-To:)"
-add_message '[from]="Sender <sender@example.com>"' \
- [to]=mailinglist@notmuchmail.org \
- [subject]=notmuch-reply-test \
- '[header]="X-Original-To: test_suite_other@notmuchmail.org"' \
- '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
- '[body]="from guessing test"'
-
-output=$(notmuch reply id:${gen_msg_id})
-test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@notmuchmail.org>
-Subject: Re: notmuch-reply-test
-To: Sender <sender@example.com>, mailinglist@notmuchmail.org
-In-Reply-To: <${gen_msg_id}>
-References: <${gen_msg_id}>
-
-On Tue, 05 Jan 2010 15:43:56 -0000, Sender <sender@example.com> wrote:
-> from guessing test"
-
-test_begin_subtest "Magic from guessing (Received: .. for ..)"
-add_message '[from]="Sender <sender@example.com>"' \
- [to]=mailinglist@notmuchmail.org \
- [subject]=notmuch-reply-test \
- "[header]=\"Received: from mail.example.com (mail.example.com [1.1.1.1])
- by mail.notmuchmail.org (some MTA) with ESMTP id 12345678
- for <test_suite_other@notmuchmail.org>; Sat, 10 Apr 2010 07:54:51 -0400 (EDT)\"" \
- '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
- '[body]="from guessing test"'
-
-output=$(notmuch reply id:${gen_msg_id})
-test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@notmuchmail.org>
-Subject: Re: notmuch-reply-test
-To: Sender <sender@example.com>, mailinglist@notmuchmail.org
-In-Reply-To: <${gen_msg_id}>
-References: <${gen_msg_id}>
-
-On Tue, 05 Jan 2010 15:43:56 -0000, Sender <sender@example.com> wrote:
-> from guessing test"
-
-test_begin_subtest "Magic from guessing (Received: domain)"
-add_message '[from]="Sender <sender@example.com>"' \
- [to]=mailinglist@notmuchmail.org \
- [subject]=notmuch-reply-test \
- "[header]=\"Received: from mail.example.com (mail.example.com [1.1.1.1])
- by mail.otherdomain.org (some MTA) with ESMTP id 12345678
- Sat, 10 Apr 2010 07:54:51 -0400 (EDT)\"" \
- '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
- '[body]="from guessing test"'
-
-output=$(notmuch reply id:${gen_msg_id})
-test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@notmuchmail.org>
-Subject: Re: notmuch-reply-test
-To: Sender <sender@example.com>, mailinglist@notmuchmail.org
-In-Reply-To: <${gen_msg_id}>
-References: <${gen_msg_id}>
-
-On Tue, 05 Jan 2010 15:43:56 -0000, Sender <sender@example.com> wrote:
-> from guessing test"
-
-test_done
+++ /dev/null
-#!/usr/bin/env bash
-
-test_description="online help"
-. ./test-lib.sh
-
-test_expect_success 'notmuch --help' 'notmuch --help'
-test_expect_success 'notmuch --help tag' 'notmuch --help tag'
-test_expect_success 'notmuch help' 'notmuch help'
-test_expect_success 'notmuch help tag' 'notmuch help tag'
-test_expect_success 'notmuch --version' 'notmuch --version'
-
-test_done
+++ /dev/null
-#!/usr/bin/env bash
-test_description="hex encoding and decoding"
-. ./test-lib.sh
-
-test_begin_subtest "round trip"
-find $TEST_DIRECTORY/corpus -type f -print | sort | xargs cat > EXPECTED
-$TEST_DIRECTORY/hex-xcode --direction=encode < EXPECTED | $TEST_DIRECTORY/hex-xcode --direction=decode > OUTPUT
-test_expect_equal_file OUTPUT EXPECTED
-
-test_begin_subtest "punctuation"
-tag1='comic_swear=$&^%$^%\\//-+$^%$'
-tag_enc1=$($TEST_DIRECTORY/hex-xcode --direction=encode "$tag1")
-test_expect_equal "$tag_enc1" "comic_swear=%24%26%5e%25%24%5e%25%5c%5c%2f%2f-+%24%5e%25%24"
-
-test_begin_subtest "round trip newlines"
-printf 'this\n tag\t has\n spaces\n' > EXPECTED.$test_count
-$TEST_DIRECTORY/hex-xcode --direction=encode < EXPECTED.$test_count |\
- $TEST_DIRECTORY/hex-xcode --direction=decode > OUTPUT.$test_count
-test_expect_equal_file EXPECTED.$test_count OUTPUT.$test_count
-
-test_begin_subtest "round trip 8bit chars"
-echo '%c3%91%c3%a5%c3%b0%c3%a3%c3%a5%c3%a9-%c3%8f%c3%8a' > EXPECTED.$test_count
-$TEST_DIRECTORY/hex-xcode --direction=decode < EXPECTED.$test_count |\
- $TEST_DIRECTORY/hex-xcode --direction=encode > OUTPUT.$test_count
-test_expect_equal_file EXPECTED.$test_count OUTPUT.$test_count
-
-test_begin_subtest "round trip (in-place)"
-find $TEST_DIRECTORY/corpus -type f -print | sort | xargs cat > EXPECTED
-$TEST_DIRECTORY/hex-xcode --in-place --direction=encode < EXPECTED |\
- $TEST_DIRECTORY/hex-xcode --in-place --direction=decode > OUTPUT
-test_expect_equal_file OUTPUT EXPECTED
-
-test_begin_subtest "punctuation (in-place)"
-tag1='comic_swear=$&^%$^%\\//-+$^%$'
-tag_enc1=$($TEST_DIRECTORY/hex-xcode --in-place --direction=encode "$tag1")
-test_expect_equal "$tag_enc1" "comic_swear=%24%26%5e%25%24%5e%25%5c%5c%2f%2f-+%24%5e%25%24"
-
-test_begin_subtest "round trip newlines (in-place)"
-printf 'this\n tag\t has\n spaces\n' > EXPECTED.$test_count
-$TEST_DIRECTORY/hex-xcode --in-place --direction=encode < EXPECTED.$test_count |\
- $TEST_DIRECTORY/hex-xcode --in-place --direction=decode > OUTPUT.$test_count
-test_expect_equal_file EXPECTED.$test_count OUTPUT.$test_count
-
-test_begin_subtest "round trip 8bit chars (in-place)"
-echo '%c3%91%c3%a5%c3%b0%c3%a3%c3%a5%c3%a9-%c3%8f%c3%8a' > EXPECTED.$test_count
-$TEST_DIRECTORY/hex-xcode --in-place --direction=decode < EXPECTED.$test_count |\
- $TEST_DIRECTORY/hex-xcode --in-place --direction=encode > OUTPUT.$test_count
-test_expect_equal_file EXPECTED.$test_count OUTPUT.$test_count
-
-test_done
+++ /dev/null
-#!/usr/bin/env bash
-test_description='hooks'
-. ./test-lib.sh
-
-HOOK_DIR=${MAIL_DIR}/.notmuch/hooks
-
-create_echo_hook () {
- local TOKEN="${RANDOM}"
- mkdir -p ${HOOK_DIR}
- cat <<EOF >"${HOOK_DIR}/${1}"
-#!/bin/sh
-echo "${TOKEN}" > ${3}
-EOF
- chmod +x "${HOOK_DIR}/${1}"
- echo "${TOKEN}" > ${2}
-}
-
-create_failing_hook () {
- mkdir -p ${HOOK_DIR}
- cat <<EOF >"${HOOK_DIR}/${1}"
-#!/bin/sh
-exit 13
-EOF
- chmod +x "${HOOK_DIR}/${1}"
-}
-
-rm_hooks () {
- rm -rf ${HOOK_DIR}
-}
-
-# add a message to generate mail dir and database
-add_message
-
-test_begin_subtest "pre-new is run"
-rm_hooks
-generate_message
-create_echo_hook "pre-new" expected output
-notmuch new > /dev/null
-test_expect_equal_file expected output
-
-test_begin_subtest "post-new is run"
-rm_hooks
-generate_message
-create_echo_hook "post-new" expected output
-notmuch new > /dev/null
-test_expect_equal_file expected output
-
-test_begin_subtest "pre-new is run before post-new"
-rm_hooks
-generate_message
-create_echo_hook "pre-new" pre-new.expected pre-new.output
-create_echo_hook "post-new" post-new.expected post-new.output
-notmuch new > /dev/null
-test_expect_equal_file post-new.expected post-new.output
-
-test_begin_subtest "pre-new non-zero exit status (hook status)"
-rm_hooks
-generate_message
-create_failing_hook "pre-new"
-output=`notmuch new 2>&1`
-test_expect_equal "$output" "Error: pre-new hook failed with status 13"
-
-# depends on the previous subtest leaving broken hook behind
-test_expect_code 1 "pre-new non-zero exit status (notmuch status)" "notmuch new"
-
-# depends on the previous subtests leaving 1 new message behind
-test_begin_subtest "pre-new non-zero exit status aborts new"
-rm_hooks
-output=$(NOTMUCH_NEW)
-test_expect_equal "$output" "Added 1 new message to the database."
-
-test_begin_subtest "post-new non-zero exit status (hook status)"
-rm_hooks
-generate_message
-create_failing_hook "post-new"
-NOTMUCH_NEW 2>output.stderr >output
-cat output.stderr >> output
-echo "Added 1 new message to the database." > expected
-echo "Error: post-new hook failed with status 13" >> expected
-test_expect_equal_file expected output
-
-# depends on the previous subtest leaving broken hook behind
-test_expect_code 1 "post-new non-zero exit status (notmuch status)" "notmuch new"
-
-# test_begin_subtest "hook without executable permissions"
-rm_hooks
-mkdir -p ${HOOK_DIR}
-cat <<EOF >"${HOOK_DIR}/pre-new"
-#!/bin/sh
-echo foo
-EOF
-output=`notmuch new 2>&1`
-test_expect_code 1 "hook without executable permissions" "notmuch new"
-
-# test_begin_subtest "hook execution failure"
-rm_hooks
-mkdir -p ${HOOK_DIR}
-cat <<EOF >"${HOOK_DIR}/pre-new"
-no hashbang, execl fails
-EOF
-chmod +x "${HOOK_DIR}/pre-new"
-test_expect_code 1 "hook execution failure" "notmuch new"
-
-test_done
+++ /dev/null
-#!/usr/bin/env bash
-test_description='"notmuch insert"'
-. ./test-lib.sh
-
-# Create directories and database before inserting.
-mkdir -p "$MAIL_DIR"/{cur,new,tmp}
-mkdir -p "$MAIL_DIR"/Drafts/{cur,new,tmp}
-notmuch new > /dev/null
-
-# We use generate_message to create the temporary message files.
-# They happen to be in the mail directory already but that is okay
-# since we do not call notmuch new hereafter.
-
-gen_insert_msg() {
- generate_message \
- "[subject]=\"insert-subject\"" \
- "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" \
- "[body]=\"insert-message\""
-}
-
-test_expect_code 1 "Insert zero-length file" \
- "notmuch insert < /dev/null"
-
-# This test is a proxy for other errors that may occur while trying to
-# add a message to the notmuch database, e.g. database locked.
-test_expect_code 0 "Insert non-message" \
- "echo bad_message | notmuch insert"
-
-test_begin_subtest "Database empty so far"
-test_expect_equal "0" "`notmuch count --output=messages '*'`"
-
-test_begin_subtest "Insert message"
-gen_insert_msg
-notmuch insert < "$gen_msg_filename"
-cur_msg_filename=$(notmuch search --output=files "subject:insert-subject")
-test_expect_equal_file "$cur_msg_filename" "$gen_msg_filename"
-
-test_begin_subtest "Insert message adds default tags"
-output=$(notmuch show --format=json "subject:insert-subject")
-expected='[[[{
- "id": "'"${gen_msg_id}"'",
- "match": true,
- "excluded": false,
- "filename": "'"${cur_msg_filename}"'",
- "timestamp": 946728000,
- "date_relative": "2000-01-01",
- "tags": ["inbox","unread"],
- "headers": {
- "Subject": "insert-subject",
- "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
- "To": "Notmuch Test Suite <test_suite@notmuchmail.org>",
- "Date": "Sat, 01 Jan 2000 12:00:00 +0000"},
- "body": [{"id": 1,
- "content-type": "text/plain",
- "content": "insert-message\n"}]},
- []]]]'
-test_expect_equal_json "$output" "$expected"
-
-test_begin_subtest "Insert duplicate message"
-notmuch insert +duptag -unread < "$gen_msg_filename"
-output=$(notmuch search --output=files "subject:insert-subject" | wc -l)
-test_expect_equal "$output" 2
-
-test_begin_subtest "Duplicate message does not change tags"
-output=$(notmuch search --format=json --output=tags "subject:insert-subject")
-test_expect_equal_json "$output" '["inbox", "unread"]'
-
-test_begin_subtest "Insert message, add tag"
-gen_insert_msg
-notmuch insert +custom < "$gen_msg_filename"
-output=$(notmuch search --output=messages tag:custom)
-test_expect_equal "$output" "id:$gen_msg_id"
-
-test_begin_subtest "Insert message, add/remove tags"
-gen_insert_msg
-notmuch insert +custom -unread < "$gen_msg_filename"
-output=$(notmuch search --output=messages tag:custom NOT tag:unread)
-test_expect_equal "$output" "id:$gen_msg_id"
-
-test_begin_subtest "Insert message with default tags stays in new/"
-gen_insert_msg
-notmuch insert < "$gen_msg_filename"
-output=$(notmuch search --output=files id:$gen_msg_id)
-dirname=$(dirname "$output")
-test_expect_equal "$dirname" "$MAIL_DIR/new"
-
-test_begin_subtest "Insert message with non-maildir synced tags stays in new/"
-gen_insert_msg
-notmuch insert +custom -inbox < "$gen_msg_filename"
-output=$(notmuch search --output=files id:$gen_msg_id)
-dirname=$(dirname "$output")
-test_expect_equal "$dirname" "$MAIL_DIR/new"
-
-test_begin_subtest "Insert message with custom new.tags goes to cur/"
-OLDCONFIG=$(notmuch config get new.tags)
-notmuch config set new.tags test
-gen_insert_msg
-notmuch insert < "$gen_msg_filename"
-output=$(notmuch search --output=files id:$gen_msg_id)
-dirname=$(dirname "$output")
-notmuch config set new.tags $OLDCONFIG
-test_expect_equal "$dirname" "$MAIL_DIR/cur"
-
-# additional check on the previous message
-test_begin_subtest "Insert message with custom new.tags actually gets the tags"
-output=$(notmuch search --output=tags id:$gen_msg_id)
-test_expect_equal "$output" "test"
-
-test_begin_subtest "Insert message with maildir synced tags goes to cur/"
-gen_insert_msg
-notmuch insert +flagged < "$gen_msg_filename"
-output=$(notmuch search --output=files id:$gen_msg_id)
-dirname=$(dirname "$output")
-test_expect_equal "$dirname" "$MAIL_DIR/cur"
-
-test_begin_subtest "Insert message into folder"
-gen_insert_msg
-notmuch insert --folder=Drafts < "$gen_msg_filename"
-output=$(notmuch search --output=files folder:Drafts)
-dirname=$(dirname "$output")
-test_expect_equal "$dirname" "$MAIL_DIR/Drafts/new"
-
-test_begin_subtest "Insert message into folder, add/remove tags"
-gen_insert_msg
-notmuch insert --folder=Drafts +draft -unread < "$gen_msg_filename"
-output=$(notmuch search --output=messages folder:Drafts tag:draft NOT tag:unread)
-test_expect_equal "$output" "id:$gen_msg_id"
-
-gen_insert_msg
-test_expect_code 1 "Insert message into non-existent folder" \
- "notmuch insert --folder=nonesuch < $gen_msg_filename"
-
-test_begin_subtest "Insert message, create folder"
-gen_insert_msg
-notmuch insert --folder=F --create-folder +folder < "$gen_msg_filename"
-output=$(notmuch search --output=files folder:F tag:folder)
-basename=$(basename "$output")
-test_expect_equal_file "$gen_msg_filename" "$MAIL_DIR/F/new/${basename}"
-
-test_begin_subtest "Insert message, create subfolder"
-gen_insert_msg
-notmuch insert --folder=F/G/H/I/J --create-folder +folder < "$gen_msg_filename"
-output=$(notmuch search --output=files folder:F/G/H/I/J tag:folder)
-basename=$(basename "$output")
-test_expect_equal_file "$gen_msg_filename" "${MAIL_DIR}/F/G/H/I/J/new/${basename}"
-
-test_begin_subtest "Insert message, create existing subfolder"
-gen_insert_msg
-notmuch insert --folder=F/G/H/I/J --create-folder +folder < "$gen_msg_filename"
-output=$(notmuch count folder:F/G/H/I/J tag:folder)
-test_expect_equal "$output" "2"
-
-gen_insert_msg
-test_expect_code 1 "Insert message, create invalid subfolder" \
- "notmuch insert --folder=../G --create-folder $gen_msg_filename"
-
-test_done
+++ /dev/null
-#!/usr/bin/env bash
-test_description="--format=json output"
-. ./test-lib.sh
-
-test_begin_subtest "Show message: json"
-add_message "[subject]=\"json-show-subject\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[bcc]=\"test_suite+bcc@notmuchmail.org\"" "[reply-to]=\"test_suite+replyto@notmuchmail.org\"" "[body]=\"json-show-message\""
-output=$(notmuch show --format=json "json-show-message")
-test_expect_equal_json "$output" "[[[{\"id\": \"${gen_msg_id}\", \"match\": true, \"excluded\": false, \"filename\": \"${gen_msg_filename}\", \"timestamp\": 946728000, \"date_relative\": \"2000-01-01\", \"tags\": [\"inbox\",\"unread\"], \"headers\": {\"Subject\": \"json-show-subject\", \"From\": \"Notmuch Test Suite <test_suite@notmuchmail.org>\", \"To\": \"Notmuch Test Suite <test_suite@notmuchmail.org>\", \"Bcc\": \"test_suite+bcc@notmuchmail.org\", \"Reply-To\": \"test_suite+replyto@notmuchmail.org\", \"Date\": \"Sat, 01 Jan 2000 12:00:00 +0000\"}, \"body\": [{\"id\": 1, \"content-type\": \"text/plain\", \"content\": \"json-show-message\n\"}]}, []]]]"
-
-# This should be the same output as above.
-test_begin_subtest "Show message: json --body=true"
-output=$(notmuch show --format=json --body=true "json-show-message")
-test_expect_equal_json "$output" "[[[{\"id\": \"${gen_msg_id}\", \"match\": true, \"excluded\": false, \"filename\": \"${gen_msg_filename}\", \"timestamp\": 946728000, \"date_relative\": \"2000-01-01\", \"tags\": [\"inbox\",\"unread\"], \"headers\": {\"Subject\": \"json-show-subject\", \"From\": \"Notmuch Test Suite <test_suite@notmuchmail.org>\", \"To\": \"Notmuch Test Suite <test_suite@notmuchmail.org>\", \"Bcc\": \"test_suite+bcc@notmuchmail.org\", \"Reply-To\": \"test_suite+replyto@notmuchmail.org\", \"Date\": \"Sat, 01 Jan 2000 12:00:00 +0000\"}, \"body\": [{\"id\": 1, \"content-type\": \"text/plain\", \"content\": \"json-show-message\n\"}]}, []]]]"
-
-test_begin_subtest "Show message: json --body=false"
-output=$(notmuch show --format=json --body=false "json-show-message")
-test_expect_equal_json "$output" "[[[{\"id\": \"${gen_msg_id}\", \"match\": true, \"excluded\": false, \"filename\": \"${gen_msg_filename}\", \"timestamp\": 946728000, \"date_relative\": \"2000-01-01\", \"tags\": [\"inbox\",\"unread\"], \"headers\": {\"Subject\": \"json-show-subject\", \"From\": \"Notmuch Test Suite <test_suite@notmuchmail.org>\", \"To\": \"Notmuch Test Suite <test_suite@notmuchmail.org>\", \"Bcc\": \"test_suite+bcc@notmuchmail.org\", \"Reply-To\": \"test_suite+replyto@notmuchmail.org\", \"Date\": \"Sat, 01 Jan 2000 12:00:00 +0000\"}}, []]]]"
-
-test_begin_subtest "Search message: json"
-add_message "[subject]=\"json-search-subject\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[body]=\"json-search-message\""
-output=$(notmuch search --format=json "json-search-message" | notmuch_search_sanitize)
-test_expect_equal_json "$output" "[{\"thread\": \"XXX\",
- \"timestamp\": 946728000,
- \"date_relative\": \"2000-01-01\",
- \"matched\": 1,
- \"total\": 1,
- \"authors\": \"Notmuch Test Suite\",
- \"subject\": \"json-search-subject\",
- \"query\": [\"id:$gen_msg_id\", null],
- \"tags\": [\"inbox\",
- \"unread\"]}]"
-
-test_begin_subtest "Show message: json, utf-8"
-add_message "[subject]=\"json-show-utf8-body-sübjéct\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[body]=\"jsön-show-méssage\""
-output=$(notmuch show --format=json "jsön-show-méssage")
-test_expect_equal_json "$output" "[[[{\"id\": \"${gen_msg_id}\", \"match\": true, \"excluded\": false, \"filename\": \"${gen_msg_filename}\", \"timestamp\": 946728000, \"date_relative\": \"2000-01-01\", \"tags\": [\"inbox\",\"unread\"], \"headers\": {\"Subject\": \"json-show-utf8-body-sübjéct\", \"From\": \"Notmuch Test Suite <test_suite@notmuchmail.org>\", \"To\": \"Notmuch Test Suite <test_suite@notmuchmail.org>\", \"Date\": \"Sat, 01 Jan 2000 12:00:00 +0000\"}, \"body\": [{\"id\": 1, \"content-type\": \"text/plain\", \"content\": \"jsön-show-méssage\n\"}]}, []]]]"
-
-test_begin_subtest "Show message: json, inline attachment filename"
-subject='json-show-inline-attachment-filename'
-id="json-show-inline-attachment-filename@notmuchmail.org"
-emacs_fcc_message \
- "$subject" \
- 'This is a test message with inline attachment with a filename' \
- "(mml-attach-file \"$TEST_DIRECTORY/README\" nil nil \"inline\")
- (message-goto-eoh)
- (insert \"Message-ID: <$id>\n\")"
-output=$(notmuch show --format=json "id:$id")
-filename=$(notmuch search --output=files "id:$id")
-# Get length of README after base64-encoding, minus additional newline.
-attachment_length=$(( $(base64 $TEST_DIRECTORY/README | wc -c) - 1 ))
-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 <test_suite@notmuchmail.org>\", \"To\": \"test_suite@notmuchmail.org\", \"Date\": \"Sat, 01 Jan 2000 12:00:00 +0000\"}, \"body\": [{\"id\": 1, \"content-type\": \"multipart/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\", \"content-length\": $attachment_length, \"content-transfer-encoding\": \"base64\", \"filename\": \"README\"}]}]}, []]]]"
-
-test_begin_subtest "Search message: json, utf-8"
-add_message "[subject]=\"json-search-utf8-body-sübjéct\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[body]=\"jsön-search-méssage\""
-output=$(notmuch search --format=json "jsön-search-méssage" | notmuch_search_sanitize)
-test_expect_equal_json "$output" "[{\"thread\": \"XXX\",
- \"timestamp\": 946728000,
- \"date_relative\": \"2000-01-01\",
- \"matched\": 1,
- \"total\": 1,
- \"authors\": \"Notmuch Test Suite\",
- \"subject\": \"json-search-utf8-body-sübjéct\",
- \"query\": [\"id:$gen_msg_id\", null],
- \"tags\": [\"inbox\",
- \"unread\"]}]"
-
-test_expect_code 20 "Format version: too low" \
- "notmuch search --format-version=0 \\*"
-
-test_expect_code 21 "Format version: too high" \
- "notmuch search --format-version=999 \\*"
-
-test_done
+++ /dev/null
-#!/usr/bin/env bash
-test_description="messages with ridiculously-long message IDs"
-. ./test-lib.sh
-
-test_begin_subtest "Referencing long ID before adding"
-generate_message '[subject]="Reference of ridiculously-long message ID"' \
- "[references]=\<abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-\>"
-output=$(NOTMUCH_NEW)
-test_expect_equal "$output" "Added 1 new message to the database."
-
-test_begin_subtest "Adding message with long ID"
-generate_message '[subject]="A ridiculously-long message ID"' \
- "[id]=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-"
-output=$(NOTMUCH_NEW)
-test_expect_equal "$output" "Added 1 new message to the database."
-
-test_begin_subtest "Referencing long ID after adding"
-generate_message '[subject]="Reply to ridiculously-long message ID"' \
- "[in-reply-to]=\<abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-\>"
-output=$(NOTMUCH_NEW)
-test_expect_equal "$output" "Added 1 new message to the database."
-
-test_begin_subtest "Ensure all messages were threaded together"
-output=$(notmuch search 'subject:"a ridiculously-long message ID"' | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2001-01-05 [1/3] Notmuch Test Suite; A ridiculously-long message ID (inbox unread)"
-
-test_done
+++ /dev/null
-#!/usr/bin/env bash
-
-test_description="maildir synchronization"
-
-. ./test-lib.sh
-
-# Create the expected maildir structure
-mkdir $MAIL_DIR/cur
-mkdir $MAIL_DIR/new
-mkdir $MAIL_DIR/tmp
-
-test_begin_subtest "Adding 'S' flag to existing filename removes 'unread' tag"
-add_message [subject]='"Adding S flag"' [filename]='adding-s-flag:2,' [dir]=cur
-output=$(notmuch search subject:"Adding S flag" | notmuch_search_sanitize)
-output+="
-"
-mv "${gen_msg_filename}" "${gen_msg_filename}S"
-output+=$(NOTMUCH_NEW)
-output+="
-"
-output+=$(notmuch search subject:"Adding S flag" | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Adding S flag (inbox unread)
-No new mail. Detected 1 file rename.
-thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Adding S flag (inbox)"
-
-test_begin_subtest "Adding message with 'S' flag prevents 'unread' tag"
-add_message [subject]='"Adding message with S"' [filename]='adding-with-s-flag:2,S' [dir]=cur
-output=$(notmuch search subject:"Adding message with S" | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Adding message with S (inbox)"
-
-test_begin_subtest "Adding 'replied' tag adds 'R' flag to filename"
-add_message [subject]='"Adding replied tag"' [filename]='adding-replied-tag:2,S' [dir]=cur
-notmuch tag +replied subject:"Adding replied tag"
-output=$(cd ${MAIL_DIR}/cur; ls -1 adding-replied*)
-test_expect_equal "$output" "adding-replied-tag:2,RS"
-
-test_begin_subtest "notmuch show works with renamed file (without notmuch new)"
-output=$(notmuch show --format=json id:${gen_msg_id} | notmuch_json_show_sanitize)
-test_expect_equal_json "$output" '[[[{"id": "XXXXX",
-"match": true,
-"excluded": false,
-"filename": "YYYYY",
-"timestamp": 42,
-"date_relative": "2001-01-05",
-"tags": ["inbox","replied"],
-"headers": {"Subject": "Adding replied tag",
-"From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
-"To": "Notmuch Test Suite <test_suite@notmuchmail.org>",
-"Date": "GENERATED_DATE"},
-"body": [{"id": 1,
-"content-type": "text/plain",
-"content": "This is just a test message (#3)\n"}]},
-[]]]]'
-
-test_expect_success 'notmuch reply works with renamed file (without notmuch new)' 'notmuch reply id:${gen_msg_id}'
-
-test_begin_subtest "notmuch new detects no file rename after tag->flag synchronization"
-output=$(NOTMUCH_NEW)
-test_expect_equal "$output" "No new mail."
-
-test_begin_subtest "When read, message moved from new to cur"
-add_message [subject]='"Message to move to cur"' [date]='"Sat, 01 Jan 2000 12:00:00 -0000"' [filename]='message-to-move-to-cur' [dir]=new
-notmuch tag -unread subject:"Message to move to cur"
-output=$(cd "$MAIL_DIR/cur"; ls message-to-move*)
-test_expect_equal "$output" "message-to-move-to-cur:2,S"
-
-test_begin_subtest "No rename should be detected by notmuch new"
-output=$(NOTMUCH_NEW)
-test_expect_equal "$output" "No new mail."
-# (*) If notmuch new was not run we've got "Processed 1 file in almost
-# no time" here. The reason is that removing unread tag in a previous
-# test created directory document in the database but this document
-# was not linked as subdirectory of $MAIL_DIR. Therefore notmuch new
-# could not reach the cur/ directory and its files in it during
-# recursive traversal.
-#
-# XXX: The above sounds like a bug that should be fixed. If notmuch is
-# creating new directories in the mail store, then it should be
-# creating all necessary database state for those directories.
-
-test_begin_subtest "Adding non-maildir tags does not move message from new to cur"
-add_message [subject]='"Message to stay in new"' \
- [date]='"Sat, 01 Jan 2000 12:00:00 -0000"' \
- [filename]='message-to-stay-in-new' [dir]=new
-notmuch tag +donotmove subject:"Message to stay in new"
-output=$(cd "$MAIL_DIR"; ls */message-to-stay-in-new*)
-test_expect_equal "$output" "new/message-to-stay-in-new"
-
-test_begin_subtest "Message in cur lacking maildir info gets one on any tag change"
-add_message [filename]='message-to-get-maildir-info' [dir]=cur
-notmuch tag +anytag id:$gen_msg_id
-output=$(cd "$MAIL_DIR"; ls */message-to-get-maildir-info*)
-test_expect_equal "$output" "cur/message-to-get-maildir-info:2,"
-
-test_begin_subtest "Message in new with maildir info is moved to cur on any tag change"
-add_message [filename]='message-with-info-to-be-moved-to-cur:2,' [dir]=new
-notmuch tag +anytag id:$gen_msg_id
-output=$(cd "$MAIL_DIR"; ls */message-with-info-to-be-moved-to-cur*)
-test_expect_equal "$output" "cur/message-with-info-to-be-moved-to-cur:2,"
-
-test_begin_subtest "Removing 'S' flag from existing filename adds 'unread' tag"
-add_message [subject]='"Removing S flag"' [filename]='removing-s-flag:2,S' [dir]=cur
-output=$(notmuch search subject:"Removing S flag" | notmuch_search_sanitize)
-output+="
-"
-mv "${gen_msg_filename}" "${gen_msg_filename%S}"
-output+=$(NOTMUCH_NEW)
-output+="
-"
-output+=$(notmuch search subject:"Removing S flag" | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Removing S flag (inbox)
-No new mail. Detected 1 file rename.
-thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Removing S flag (inbox unread)"
-
-test_begin_subtest "Removing info from filename leaves tags unchanged"
-add_message [subject]='"Message to lose maildir info"' [filename]='message-to-lose-maildir-info' [dir]=cur
-notmuch tag -unread subject:"Message to lose maildir info"
-mv "$MAIL_DIR/cur/message-to-lose-maildir-info:2,S" "$MAIL_DIR/cur/message-without-maildir-info"
-output=$(NOTMUCH_NEW)
-output+="
-"
-output+=$(notmuch search subject:"Message to lose maildir info" | notmuch_search_sanitize)
-test_expect_equal "$output" "No new mail. Detected 1 file rename.
-thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Message to lose maildir info (inbox)"
-
-add_message [subject]='"Non-maildir message"' [dir]=notmaildir [filename]='non-maildir-message'
-expected=$(notmuch search --output=files subject:"Non-maildir message")
-test_expect_success "Can remove unread tag from message in non-maildir directory" 'notmuch tag -unread subject:"Non-maildir message"'
-
-test_begin_subtest "Message in non-maildir directory does not get renamed"
-output=$(notmuch search --output=files subject:"Non-maildir message")
-test_expect_equal "$output" "$expected"
-
-test_begin_subtest "notmuch dump/restore re-synchronizes maildir tags with flags"
-# Capture current filename state
-expected=$(ls $MAIL_DIR/cur)
-# Add/remove some flags from filenames
-mv $MAIL_DIR/cur/adding-replied-tag:2,RS $MAIL_DIR/cur/adding-replied-tag:2,S
-mv $MAIL_DIR/cur/adding-s-flag:2,S $MAIL_DIR/cur/adding-s-flag:2,
-mv $MAIL_DIR/cur/adding-with-s-flag:2,S $MAIL_DIR/cur/adding-with-s-flag:2,RS
-mv $MAIL_DIR/cur/message-to-move-to-cur:2,S $MAIL_DIR/cur/message-to-move-to-cur:2,DS
-notmuch dump --output=dump.txt
-NOTMUCH_NEW >/dev/null
-notmuch restore --input=dump.txt
-output=$(ls $MAIL_DIR/cur)
-test_expect_equal "$output" "$expected"
-
-test_begin_subtest 'Adding flags to duplicate message tags the mail'
-add_message [subject]='"Duplicated message"' [dir]=cur [filename]='duplicated-message:2,'
-cp "$MAIL_DIR/cur/duplicated-message:2," "$MAIL_DIR/cur/duplicated-message-copy:2,RS"
-NOTMUCH_NEW > output
-notmuch search subject:"Duplicated message" | notmuch_search_sanitize >> output
-test_expect_equal "$(< output)" "No new mail.
-thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Duplicated message (inbox replied)"
-
-test_begin_subtest "Adding duplicate message without flags does not remove tags"
-cp "$MAIL_DIR/cur/duplicated-message-copy:2,RS" "$MAIL_DIR/cur/duplicated-message-another-copy:2,"
-NOTMUCH_NEW > output
-notmuch search subject:"Duplicated message" | notmuch_search_sanitize >> output
-test_expect_equal "$(< output)" "No new mail.
-thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Duplicated message (inbox replied)"
-
-test_begin_subtest "Tag changes modify flags of multiple files"
-notmuch tag -replied subject:"Duplicated message"
-(cd $MAIL_DIR/cur/; ls duplicated*) > actual
-test_expect_equal "$(< actual)" "duplicated-message-another-copy:2,S
-duplicated-message-copy:2,S
-duplicated-message:2,S"
-
-test_begin_subtest "Synchronizing tag changes preserves unsupported maildir flags"
-add_message [subject]='"Unsupported maildir flags"' [dir]=cur [filename]='unsupported-maildir-flags:2,FSZxyz'
-notmuch tag +unread +draft -flagged subject:"Unsupported maildir flags"
-test_expect_equal "$(cd $MAIL_DIR/cur/; ls unsupported*)" "unsupported-maildir-flags:2,DZxyz"
-
-test_begin_subtest "A file with non-compliant maildir info will not be renamed"
-add_message [subject]='"Non-compliant maildir info"' [dir]=cur [filename]='non-compliant-maildir-info:2,These-are-not-flags-in-ASCII-order-donottouch'
-notmuch tag +unread +draft -flagged subject:"Non-compliant maildir info"
-test_expect_equal "$(cd $MAIL_DIR/cur/; ls non-compliant*)" "non-compliant-maildir-info:2,These-are-not-flags-in-ASCII-order-donottouch"
-
-test_begin_subtest "Files in new/ get default synchronized tags"
-OLDCONFIG=$(notmuch config get new.tags)
-notmuch config set new.tags test
-add_message [subject]='"File in new/"' [dir]=new [filename]='file-in-new'
-notmuch config set new.tags $OLDCONFIG
-notmuch search 'subject:"File in new"' | notmuch_search_sanitize > output
-test_expect_equal "$(< output)" \
-"thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; File in new/ (test unread)"
-
-test_done
+++ /dev/null
-#!/usr/bin/env bash
-test_description='messages with missing headers'
-. ./test-lib.sh
-
-# Notmuch requires at least one of from, subject, or to or it will
-# ignore the file. Generate two messages so that together they cover
-# all possible missing headers. We also give one of the messages a
-# date to ensure stable result ordering.
-
-cat <<EOF > "${MAIL_DIR}/msg-2"
-To: Notmuch Test Suite <test_suite@notmuchmail.org>
-Date: Fri, 05 Jan 2001 15:43:57 +0000
-
-Body
-EOF
-
-cat <<EOF > "${MAIL_DIR}/msg-1"
-From: Notmuch Test Suite <test_suite@notmuchmail.org>
-
-Body
-EOF
-
-NOTMUCH_NEW
-
-test_begin_subtest "Search: text"
-output=$(notmuch search '*' | notmuch_search_sanitize)
-test_expect_equal "$output" "\
-thread:XXX 2001-01-05 [1/1] (null); (inbox unread)
-thread:XXX 1970-01-01 [1/1] Notmuch Test Suite; (inbox unread)"
-
-test_begin_subtest "Search: json"
-output=$(notmuch search --format=json '*' | notmuch_search_sanitize)
-test_expect_equal_json "$output" '
-[
- {
- "authors": "",
- "date_relative": "2001-01-05",
- "matched": 1,
- "subject": "",
- "tags": [
- "inbox",
- "unread"
- ],
- "thread": "XXX",
- "timestamp": 978709437,
- "total": 1,
- "query": ["id:notmuch-sha1-7a6e4eac383ef958fcd3ebf2143db71b8ff01161", null]
- },
- {
- "authors": "Notmuch Test Suite",
- "date_relative": "1970-01-01",
- "matched": 1,
- "subject": "",
- "tags": [
- "inbox",
- "unread"
- ],
- "thread": "XXX",
- "timestamp": 0,
- "total": 1,
- "query": ["id:notmuch-sha1-ca55943aff7a72baf2ab21fa74fab3d632401334", null]
- }
-]'
-
-test_begin_subtest "Show: text"
-output=$(notmuch show '*' | notmuch_show_sanitize)
-test_expect_equal "$output" "\
-\fmessage{ id:notmuch-sha1-7a6e4eac383ef958fcd3ebf2143db71b8ff01161 depth:0 match:1 excluded:0 filename:/XXX/mail/msg-2
-\fheader{
- (2001-01-05) (inbox unread)
-Subject: (null)
-From: (null)
-To: Notmuch Test Suite <test_suite@notmuchmail.org>
-Date: Fri, 05 Jan 2001 15:43:57 +0000
-\fheader}
-\fbody{
-\fpart{ ID: 1, Content-type: text/plain
-Body
-\fpart}
-\fbody}
-\fmessage}
-\fmessage{ id:notmuch-sha1-ca55943aff7a72baf2ab21fa74fab3d632401334 depth:0 match:1 excluded:0 filename:/XXX/mail/msg-1
-\fheader{
-Notmuch Test Suite <test_suite@notmuchmail.org> (1970-01-01) (inbox unread)
-Subject: (null)
-From: Notmuch Test Suite <test_suite@notmuchmail.org>
-Date: Thu, 01 Jan 1970 00:00:00 +0000
-\fheader}
-\fbody{
-\fpart{ ID: 1, Content-type: text/plain
-Body
-\fpart}
-\fbody}
-\fmessage}"
-
-test_begin_subtest "Show: json"
-output=$(notmuch show --format=json '*' | notmuch_json_show_sanitize)
-expected=$(notmuch_json_show_sanitize <<EOF
-[
- [
- [
- {
- "body": [
- {
- "content": "Body\n",
- "content-type": "text/plain",
- "id": 1
- }
- ],
- "date_relative": "2001-01-05",
- "excluded": false,
- "filename": "YYYYY",
- "headers": {
- "Date": "Fri, 05 Jan 2001 15:43:57 +0000",
- "From": "",
- "Subject": "",
- "To": "Notmuch Test Suite <test_suite@notmuchmail.org>"
- },
- "id": "XXXXX",
- "match": true,
- "tags": [
- "inbox",
- "unread"
- ],
- "timestamp": 978709437
- },
- []
- ]
- ],
- [
- [
- {
- "body": [
- {
- "content": "Body\n",
- "content-type": "text/plain",
- "id": 1
- }
- ],
- "date_relative": "1970-01-01",
- "excluded": false,
- "filename": "YYYYY",
- "headers": {
- "Date": "Thu, 01 Jan 1970 00:00:00 +0000",
- "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
- "Subject": ""
- },
- "id": "XXXXX",
- "match": true,
- "tags": [
- "inbox",
- "unread"
- ],
- "timestamp": 0
- },
- []
- ]
- ]
-]
-EOF
-)
-test_expect_equal_json "$output" "$expected"
-
-test_done
+++ /dev/null
-#!/usr/bin/env bash
-test_description="output of multipart message"
-. ./test-lib.sh
-
-cat <<EOF > embedded_message
-From: Carl Worth <cworth@cworth.org>
-To: cworth@cworth.org
-Subject: html message
-Date: Fri, 05 Jan 2001 15:42:57 +0000
-User-Agent: Notmuch/0.5 (http://notmuchmail.org) Emacs/23.3.1 (i486-pc-linux-gnu)
-Message-ID: <87liy5ap01.fsf@yoom.home.cworth.org>
-MIME-Version: 1.0
-Content-Type: multipart/alternative; boundary="==-=-=="
-
---==-=-==
-Content-Type: text/html
-
-<p>This is an embedded message, with a multipart/alternative part.</p>
-
---==-=-==
-Content-Type: text/plain
-
-This is an embedded message, with a multipart/alternative part.
-
---==-=-==--
-EOF
-
-cat <<EOF > ${MAIL_DIR}/multipart
-From: Carl Worth <cworth@cworth.org>
-To: cworth@cworth.org
-Subject: Multipart message
-Date: Fri, 05 Jan 2001 15:43:57 +0000
-User-Agent: Notmuch/0.5 (http://notmuchmail.org) Emacs/23.3.1 (i486-pc-linux-gnu)
-Message-ID: <87liy5ap00.fsf@yoom.home.cworth.org>
-MIME-Version: 1.0
-Content-Type: multipart/signed; boundary="==-=-=";
- micalg=pgp-sha1; protocol="application/pgp-signature"
-
---==-=-=
-Content-Type: multipart/mixed; boundary="=-=-="
-
---=-=-=
-Content-Type: message/rfc822
-Content-Disposition: inline
-
-EOF
-cat embedded_message >> ${MAIL_DIR}/multipart
-cat <<EOF >> ${MAIL_DIR}/multipart
-
---=-=-=
-Content-Disposition: attachment; filename=attachment
-
-This is a text attachment.
-
---=-=-=
-
-And this message is signed.
-
--Carl
-
---=-=-=--
-
---==-=-=
-Content-Type: application/pgp-signature
-
------BEGIN PGP SIGNATURE-----
-Version: GnuPG v1.4.11 (GNU/Linux)
-
-iEYEARECAAYFAk3SA/gACgkQ6JDdNq8qSWj0sACghqVJEQJUs3yV8zbTzhgnSIcD
-W6cAmQE4dcYrx/LPLtYLZm1jsGauE5hE
-=zkga
------END PGP SIGNATURE-----
---==-=-=--
-EOF
-
-cat <<EOF > ${MAIL_DIR}/base64-part-with-crlf
-From: Carl Worth <cworth@cworth.org>
-To: cworth@cworth.org
-Subject: Test message with a BASE64 encoded binary containing CRLF pair
-Date: Fri, 05 Jan 2001 15:43:57 +0000
-User-Agent: Notmuch/0.5 (http://notmuchmail.org) Emacs/23.3.1 (i486-pc-linux-gnu)
-Message-ID: <base64-part-with-crlf>
-MIME-Version: 1.0
-Content-Type: multipart/mixed; boundary="==-=-=";
-
---==-=-=
-
-The attached BASE64-encoded part expands to a binary containing a CRLF
-pair (that is one bye of 0x0D followed by one byte of 0x0A). This is
-designed to ensure that notmuch is not corrupting the output of this
-part by converting the CRLF pair to an LF only (as would be appropriate
-for display of a text part on a Linux system, for example).
-
-The part should be a 3-byte file with the following sequence of 3
-hexadecimal bytes:
-
- EF 0D 0A
-
---==-=-=
-Content-Type: application/octet-stream
-Content-Disposition: attachment; filename=crlf.bin
-Content-Transfer-Encoding: base64
-
-7w0K
---==-=-=--
-EOF
-notmuch new > /dev/null
-
-test_begin_subtest "--format=text --part=0, full message"
-notmuch show --format=text --part=0 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
-cat <<EOF >EXPECTED
-\fmessage{ id:87liy5ap00.fsf@yoom.home.cworth.org depth:0 match:1 excluded:0 filename:${MAIL_DIR}/multipart
-\fheader{
-Carl Worth <cworth@cworth.org> (2001-01-05) (attachment inbox signed unread)
-Subject: Multipart message
-From: Carl Worth <cworth@cworth.org>
-To: cworth@cworth.org
-Date: Fri, 05 Jan 2001 15:43:57 +0000
-\fheader}
-\fbody{
-\fpart{ ID: 1, Content-type: multipart/signed
-\fpart{ ID: 2, Content-type: multipart/mixed
-\fpart{ ID: 3, Content-type: message/rfc822
-\fheader{
-Subject: html message
-From: Carl Worth <cworth@cworth.org>
-To: cworth@cworth.org
-Date: Fri, 05 Jan 2001 15:42:57 +0000
-\fheader}
-\fbody{
-\fpart{ ID: 4, Content-type: multipart/alternative
-\fpart{ ID: 5, Content-type: text/html
-Non-text part: text/html
-\fpart}
-\fpart{ ID: 6, Content-type: text/plain
-This is an embedded message, with a multipart/alternative part.
-\fpart}
-\fpart}
-\fbody}
-\fpart}
-\fattachment{ ID: 7, Filename: attachment, Content-type: text/plain
-This is a text attachment.
-\fattachment}
-\fpart{ ID: 8, Content-type: text/plain
-And this message is signed.
-
--Carl
-\fpart}
-\fpart}
-\fpart{ ID: 9, Content-type: application/pgp-signature
-Non-text part: application/pgp-signature
-\fpart}
-\fpart}
-\fbody}
-\fmessage}
-EOF
-test_expect_equal_file OUTPUT EXPECTED
-
-test_begin_subtest "--format=text --part=1, message body"
-notmuch show --format=text --part=1 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
-cat <<EOF >EXPECTED
-\fpart{ ID: 1, Content-type: multipart/signed
-\fpart{ ID: 2, Content-type: multipart/mixed
-\fpart{ ID: 3, Content-type: message/rfc822
-\fheader{
-Subject: html message
-From: Carl Worth <cworth@cworth.org>
-To: cworth@cworth.org
-Date: Fri, 05 Jan 2001 15:42:57 +0000
-\fheader}
-\fbody{
-\fpart{ ID: 4, Content-type: multipart/alternative
-\fpart{ ID: 5, Content-type: text/html
-Non-text part: text/html
-\fpart}
-\fpart{ ID: 6, Content-type: text/plain
-This is an embedded message, with a multipart/alternative part.
-\fpart}
-\fpart}
-\fbody}
-\fpart}
-\fattachment{ ID: 7, Filename: attachment, Content-type: text/plain
-This is a text attachment.
-\fattachment}
-\fpart{ ID: 8, Content-type: text/plain
-And this message is signed.
-
--Carl
-\fpart}
-\fpart}
-\fpart{ ID: 9, Content-type: application/pgp-signature
-Non-text part: application/pgp-signature
-\fpart}
-\fpart}
-EOF
-test_expect_equal_file OUTPUT EXPECTED
-
-test_begin_subtest "--format=text --part=2, multipart/mixed"
-notmuch show --format=text --part=2 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
-cat <<EOF >EXPECTED
-\fpart{ ID: 2, Content-type: multipart/mixed
-\fpart{ ID: 3, Content-type: message/rfc822
-\fheader{
-Subject: html message
-From: Carl Worth <cworth@cworth.org>
-To: cworth@cworth.org
-Date: Fri, 05 Jan 2001 15:42:57 +0000
-\fheader}
-\fbody{
-\fpart{ ID: 4, Content-type: multipart/alternative
-\fpart{ ID: 5, Content-type: text/html
-Non-text part: text/html
-\fpart}
-\fpart{ ID: 6, Content-type: text/plain
-This is an embedded message, with a multipart/alternative part.
-\fpart}
-\fpart}
-\fbody}
-\fpart}
-\fattachment{ ID: 7, Filename: attachment, Content-type: text/plain
-This is a text attachment.
-\fattachment}
-\fpart{ ID: 8, Content-type: text/plain
-And this message is signed.
-
--Carl
-\fpart}
-\fpart}
-EOF
-test_expect_equal_file OUTPUT EXPECTED
-
-test_begin_subtest "--format=text --part=3, rfc822 part"
-notmuch show --format=text --part=3 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
-cat <<EOF >EXPECTED
-\fpart{ ID: 3, Content-type: message/rfc822
-\fheader{
-Subject: html message
-From: Carl Worth <cworth@cworth.org>
-To: cworth@cworth.org
-Date: Fri, 05 Jan 2001 15:42:57 +0000
-\fheader}
-\fbody{
-\fpart{ ID: 4, Content-type: multipart/alternative
-\fpart{ ID: 5, Content-type: text/html
-Non-text part: text/html
-\fpart}
-\fpart{ ID: 6, Content-type: text/plain
-This is an embedded message, with a multipart/alternative part.
-\fpart}
-\fpart}
-\fbody}
-\fpart}
-EOF
-test_expect_equal_file OUTPUT EXPECTED
-
-test_begin_subtest "--format=text --part=4, rfc822's multipart"
-notmuch show --format=text --part=4 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
-cat <<EOF >EXPECTED
-\fpart{ ID: 4, Content-type: multipart/alternative
-\fpart{ ID: 5, Content-type: text/html
-Non-text part: text/html
-\fpart}
-\fpart{ ID: 6, Content-type: text/plain
-This is an embedded message, with a multipart/alternative part.
-\fpart}
-\fpart}
-EOF
-test_expect_equal_file OUTPUT EXPECTED
-
-test_begin_subtest "--format=text --part=5, rfc822's html part"
-notmuch show --format=text --part=5 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
-cat <<EOF >EXPECTED
-\fpart{ ID: 5, Content-type: text/html
-Non-text part: text/html
-\fpart}
-EOF
-test_expect_equal_file OUTPUT EXPECTED
-
-test_begin_subtest "--format=text --part=6, rfc822's text part"
-notmuch show --format=text --part=6 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
-cat <<EOF >EXPECTED
-\fpart{ ID: 6, Content-type: text/plain
-This is an embedded message, with a multipart/alternative part.
-\fpart}
-EOF
-test_expect_equal_file OUTPUT EXPECTED
-
-test_begin_subtest "--format=text --part=7, inline attachement"
-notmuch show --format=text --part=7 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
-cat <<EOF >EXPECTED
-\fattachment{ ID: 7, Filename: attachment, Content-type: text/plain
-This is a text attachment.
-\fattachment}
-EOF
-test_expect_equal_file OUTPUT EXPECTED
-
-test_begin_subtest "--format=text --part=8, plain text part"
-notmuch show --format=text --part=8 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
-cat <<EOF >EXPECTED
-\fpart{ ID: 8, Content-type: text/plain
-And this message is signed.
-
--Carl
-\fpart}
-EOF
-test_expect_equal_file OUTPUT EXPECTED
-
-test_begin_subtest "--format=text --part=9, pgp signature (unverified)"
-notmuch show --format=text --part=9 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
-cat <<EOF >EXPECTED
-\fpart{ ID: 9, Content-type: application/pgp-signature
-Non-text part: application/pgp-signature
-\fpart}
-EOF
-test_expect_equal_file OUTPUT EXPECTED
-
-test_expect_success \
- "--format=text --part=8, no part, expect error" \
- "notmuch show --format=text --part=8 'id:87liy5ap00.fsf@yoom.home.cworth.org'"
-
-test_begin_subtest "--format=json --part=0, full message"
-notmuch show --format=json --part=0 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
-cat <<EOF >EXPECTED
-{"id": "87liy5ap00.fsf@yoom.home.cworth.org", "match": true, "excluded": false, "filename": "${MAIL_DIR}/multipart", "timestamp": 978709437, "date_relative": "2001-01-05", "tags": ["attachment","inbox","signed","unread"], "headers": {"Subject": "Multipart message", "From": "Carl Worth <cworth@cworth.org>", "To": "cworth@cworth.org", "Date": "Fri, 05 Jan 2001 15:43:57 +0000"}, "body": [
-{"id": 1, "content-type": "multipart/signed", "content": [
-{"id": 2, "content-type": "multipart/mixed", "content": [
-{"id": 3, "content-type": "message/rfc822", "content": [{"headers": {"Subject": "html message", "From": "Carl Worth <cworth@cworth.org>", "To": "cworth@cworth.org", "Date": "Fri, 05 Jan 2001 15:42:57 +0000"}, "body": [
-{"id": 4, "content-type": "multipart/alternative", "content": [
-{"id": 5, "content-type": "text/html", "content-length": 71},
-{"id": 6, "content-type": "text/plain", "content": "This is an embedded message, with a multipart/alternative part.\n"}]}]}]},
-{"id": 7, "content-type": "text/plain", "filename": "attachment", "content": "This is a text attachment.\n"},
-{"id": 8, "content-type": "text/plain", "content": "And this message is signed.\n\n-Carl\n"}]},
-{"id": 9, "content-type": "application/pgp-signature", "content-length": 197}]}]}
-EOF
-test_expect_equal_json "$(cat OUTPUT)" "$(cat EXPECTED)"
-
-test_begin_subtest "--format=json --part=1, message body"
-notmuch show --format=json --part=1 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
-cat <<EOF >EXPECTED
-{"id": 1, "content-type": "multipart/signed", "content": [
-{"id": 2, "content-type": "multipart/mixed", "content": [
-{"id": 3, "content-type": "message/rfc822", "content": [{"headers": {"Subject": "html message", "From": "Carl Worth <cworth@cworth.org>", "To": "cworth@cworth.org", "Date": "Fri, 05 Jan 2001 15:42:57 +0000"}, "body": [
-{"id": 4, "content-type": "multipart/alternative", "content": [
-{"id": 5, "content-type": "text/html", "content-length": 71},
-{"id": 6, "content-type": "text/plain", "content": "This is an embedded message, with a multipart/alternative part.\n"}]}]}]},
-{"id": 7, "content-type": "text/plain", "filename": "attachment", "content": "This is a text attachment.\n"},
-{"id": 8, "content-type": "text/plain", "content": "And this message is signed.\n\n-Carl\n"}]},
-{"id": 9, "content-type": "application/pgp-signature", "content-length": 197}]}
-EOF
-test_expect_equal_json "$(cat OUTPUT)" "$(cat EXPECTED)"
-
-test_begin_subtest "--format=json --part=2, multipart/mixed"
-notmuch show --format=json --part=2 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
-cat <<EOF >EXPECTED
-{"id": 2, "content-type": "multipart/mixed", "content": [
-{"id": 3, "content-type": "message/rfc822", "content": [{"headers": {"Subject": "html message", "From": "Carl Worth <cworth@cworth.org>", "To": "cworth@cworth.org", "Date": "Fri, 05 Jan 2001 15:42:57 +0000"}, "body": [
-{"id": 4, "content-type": "multipart/alternative", "content": [
-{"id": 5, "content-type": "text/html", "content-length": 71},
-{"id": 6, "content-type": "text/plain", "content": "This is an embedded message, with a multipart/alternative part.\n"}]}]}]},
-{"id": 7, "content-type": "text/plain", "filename": "attachment", "content": "This is a text attachment.\n"},
-{"id": 8, "content-type": "text/plain", "content": "And this message is signed.\n\n-Carl\n"}]}
-EOF
-test_expect_equal_json "$(cat OUTPUT)" "$(cat EXPECTED)"
-
-test_begin_subtest "--format=json --part=3, rfc822 part"
-notmuch show --format=json --part=3 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
-cat <<EOF >EXPECTED
-{"id": 3, "content-type": "message/rfc822", "content": [{"headers": {"Subject": "html message", "From": "Carl Worth <cworth@cworth.org>", "To": "cworth@cworth.org", "Date": "Fri, 05 Jan 2001 15:42:57 +0000"}, "body": [
-{"id": 4, "content-type": "multipart/alternative", "content": [
-{"id": 5, "content-type": "text/html", "content-length": 71},
-{"id": 6, "content-type": "text/plain", "content": "This is an embedded message, with a multipart/alternative part.\n"}]}]}]}
-EOF
-test_expect_equal_json "$(cat OUTPUT)" "$(cat EXPECTED)"
-
-test_begin_subtest "--format=json --part=4, rfc822's multipart/alternative"
-notmuch show --format=json --part=4 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
-cat <<EOF >EXPECTED
-{"id": 4, "content-type": "multipart/alternative", "content": [
-{"id": 5, "content-type": "text/html", "content-length": 71},
-{"id": 6, "content-type": "text/plain", "content": "This is an embedded message, with a multipart/alternative part.\n"}]}
-EOF
-test_expect_equal_json "$(cat OUTPUT)" "$(cat EXPECTED)"
-
-test_begin_subtest "--format=json --part=5, rfc822's html part"
-notmuch show --format=json --part=5 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
-cat <<EOF >EXPECTED
-{"id": 5, "content-type": "text/html", "content-length": 71}
-EOF
-test_expect_equal_json "$(cat OUTPUT)" "$(cat EXPECTED)"
-
-test_begin_subtest "--format=json --part=6, rfc822's text part"
-notmuch show --format=json --part=6 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
-cat <<EOF >EXPECTED
-{"id": 6, "content-type": "text/plain", "content": "This is an embedded message, with a multipart/alternative part.\n"}
-EOF
-test_expect_equal_json "$(cat OUTPUT)" "$(cat EXPECTED)"
-
-test_begin_subtest "--format=json --part=7, inline attachment"
-notmuch show --format=json --part=7 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
-cat <<EOF >EXPECTED
-{"id": 7, "content-type": "text/plain", "filename": "attachment", "content": "This is a text attachment.\n"}
-EOF
-test_expect_equal_json "$(cat OUTPUT)" "$(cat EXPECTED)"
-
-test_begin_subtest "--format=json --part=8, plain text part"
-notmuch show --format=json --part=8 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
-cat <<EOF >EXPECTED
-{"id": 8, "content-type": "text/plain", "content": "And this message is signed.\n\n-Carl\n"}
-EOF
-test_expect_equal_json "$(cat OUTPUT)" "$(cat EXPECTED)"
-
-test_begin_subtest "--format=json --part=9, pgp signature (unverified)"
-notmuch show --format=json --part=9 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
-cat <<EOF >EXPECTED
-{"id": 9, "content-type": "application/pgp-signature", "content-length": 197}
-EOF
-test_expect_equal_json "$(cat OUTPUT)" "$(cat EXPECTED)"
-
-test_expect_success \
- "--format=json --part=10, no part, expect error" \
- "notmuch show --format=json --part=10 'id:87liy5ap00.fsf@yoom.home.cworth.org'"
-
-test_begin_subtest "--format=raw"
-notmuch show --format=raw 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
-test_expect_equal_file OUTPUT "${MAIL_DIR}"/multipart
-
-test_begin_subtest "--format=raw --part=0, full message"
-notmuch show --format=raw --part=0 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
-test_expect_equal_file OUTPUT "${MAIL_DIR}"/multipart
-
-test_begin_subtest "--format=raw --part=1, message body"
-notmuch show --format=raw --part=1 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
-test_expect_equal_file OUTPUT "${MAIL_DIR}"/multipart
-
-test_begin_subtest "--format=raw --part=2, multipart/mixed"
-notmuch show --format=raw --part=2 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
-cat <<EOF >EXPECTED
-Content-Type: multipart/mixed; boundary="=-=-="
-
---=-=-=
-Content-Type: message/rfc822
-Content-Disposition: inline
-
-From: Carl Worth <cworth@cworth.org>
-To: cworth@cworth.org
-Subject: html message
-Date: Fri, 05 Jan 2001 15:42:57 +0000
-User-Agent: Notmuch/0.5 (http://notmuchmail.org) Emacs/23.3.1 (i486-pc-linux-gnu)
-Message-ID: <87liy5ap01.fsf@yoom.home.cworth.org>
-MIME-Version: 1.0
-Content-Type: multipart/alternative; boundary="==-=-=="
-
---==-=-==
-Content-Type: text/html
-
-<p>This is an embedded message, with a multipart/alternative part.</p>
-
---==-=-==
-Content-Type: text/plain
-
-This is an embedded message, with a multipart/alternative part.
-
---==-=-==--
-
---=-=-=
-Content-Disposition: attachment; filename=attachment
-
-This is a text attachment.
-
---=-=-=
-
-And this message is signed.
-
--Carl
-
---=-=-=--
-EOF
-test_expect_equal_file OUTPUT EXPECTED
-
-test_begin_subtest "--format=raw --part=3, rfc822 part"
-notmuch show --format=raw --part=3 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
-test_expect_equal_file OUTPUT embedded_message
-
-test_begin_subtest "--format=raw --part=4, rfc822's multipart"
-notmuch show --format=raw --part=4 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
-cat <<EOF >EXPECTED
-From: Carl Worth <cworth@cworth.org>
-To: cworth@cworth.org
-Subject: html message
-Date: Fri, 05 Jan 2001 15:42:57 +0000
-User-Agent: Notmuch/0.5 (http://notmuchmail.org) Emacs/23.3.1 (i486-pc-linux-gnu)
-Message-ID: <87liy5ap01.fsf@yoom.home.cworth.org>
-MIME-Version: 1.0
-Content-Type: multipart/alternative; boundary="==-=-=="
-
---==-=-==
-Content-Type: text/html
-
-<p>This is an embedded message, with a multipart/alternative part.</p>
-
---==-=-==
-Content-Type: text/plain
-
-This is an embedded message, with a multipart/alternative part.
-
---==-=-==--
-EOF
-test_expect_equal_file OUTPUT EXPECTED
-
-test_begin_subtest "--format=raw --part=5, rfc822's html part"
-notmuch show --format=raw --part=5 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
-cat <<EOF >EXPECTED
-<p>This is an embedded message, with a multipart/alternative part.</p>
-EOF
-test_expect_equal_file OUTPUT EXPECTED
-
-test_begin_subtest "--format=raw --part=6, rfc822's text part"
-notmuch show --format=raw --part=6 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
-cat <<EOF >EXPECTED
-This is an embedded message, with a multipart/alternative part.
-EOF
-test_expect_equal_file OUTPUT EXPECTED
-
-test_begin_subtest "--format=raw --part=7, inline attachment"
-notmuch show --format=raw --part=7 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
-cat <<EOF >EXPECTED
-This is a text attachment.
-EOF
-test_expect_equal_file OUTPUT EXPECTED
-
-test_begin_subtest "--format=raw --part=8, plain text part"
-notmuch show --format=raw --part=8 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
-cat <<EOF >EXPECTED
-And this message is signed.
-
--Carl
-EOF
-test_expect_equal_file OUTPUT EXPECTED
-
-test_begin_subtest "--format=raw --part=9, pgp signature (unverified)"
-notmuch show --format=raw --part=9 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
-# output should *not* include newline
-echo >>OUTPUT
-cat <<EOF >EXPECTED
------BEGIN PGP SIGNATURE-----
-Version: GnuPG v1.4.11 (GNU/Linux)
-
-iEYEARECAAYFAk3SA/gACgkQ6JDdNq8qSWj0sACghqVJEQJUs3yV8zbTzhgnSIcD
-W6cAmQE4dcYrx/LPLtYLZm1jsGauE5hE
-=zkga
------END PGP SIGNATURE-----
-EOF
-test_expect_equal_file OUTPUT EXPECTED
-
-test_expect_success \
- "--format=raw --part=10, no part, expect error" \
- "notmuch show --format=raw --part=8 'id:87liy5ap00.fsf@yoom.home.cworth.org'"
-
-test_begin_subtest "--format=mbox"
-notmuch show --format=mbox 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
-printf "From cworth@cworth.org Fri Jan 5 15:43:57 2001\n" >EXPECTED
-cat "${MAIL_DIR}"/multipart >>EXPECTED
-# mbox output is expected to include a blank line
-echo >>EXPECTED
-test_expect_equal_file OUTPUT EXPECTED
-
-test_expect_success \
- "--format=mbox --part=1, incompatible, expect error" \
- "! notmuch show --format=mbox --part=1 'id:87liy5ap00.fsf@yoom.home.cworth.org'"
-
-test_begin_subtest "'notmuch reply' to a multipart message"
-notmuch reply 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
-cat <<EOF >EXPECTED
-From: Notmuch Test Suite <test_suite@notmuchmail.org>
-Subject: Re: Multipart message
-To: Carl Worth <cworth@cworth.org>, cworth@cworth.org
-In-Reply-To: <87liy5ap00.fsf@yoom.home.cworth.org>
-References: <87liy5ap00.fsf@yoom.home.cworth.org>
-
-On Fri, 05 Jan 2001 15:43:57 +0000, Carl Worth <cworth@cworth.org> wrote:
-> From: Carl Worth <cworth@cworth.org>
-> To: cworth@cworth.org
-> Subject: html message
-> Date: Fri, 05 Jan 2001 15:42:57 +0000
->
-Non-text part: text/html
-> This is an embedded message, with a multipart/alternative part.
-> This is a text attachment.
-> And this message is signed.
->
-> -Carl
-EOF
-test_expect_equal_file OUTPUT EXPECTED
-
-test_begin_subtest "'notmuch reply' to a multipart message with json format"
-notmuch reply --format=json 'id:87liy5ap00.fsf@yoom.home.cworth.org' | notmuch_json_show_sanitize >OUTPUT
-notmuch_json_show_sanitize <<EOF >EXPECTED
-{"reply-headers": {"Subject": "Re: Multipart message",
- "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
- "To": "Carl Worth <cworth@cworth.org>, cworth@cworth.org",
- "In-reply-to": "<87liy5ap00.fsf@yoom.home.cworth.org>",
- "References": "<87liy5ap00.fsf@yoom.home.cworth.org>"},
- "original": {"id": "XXXXX",
- "match": false,
- "excluded": false,
- "filename": "YYYYY",
- "timestamp": 978709437,
- "date_relative": "2001-01-05",
- "tags": ["attachment","inbox","signed","unread"],
- "headers": {"Subject": "Multipart message",
- "From": "Carl Worth <cworth@cworth.org>",
- "To": "cworth@cworth.org",
- "Date": "Fri, 05 Jan 2001 15:43:57 +0000"},
- "body": [{"id": 1,
- "content-type": "multipart/signed",
- "content": [{"id": 2,
- "content-type": "multipart/mixed",
- "content": [{"id": 3,
- "content-type": "message/rfc822",
- "content": [{"headers": {"Subject": "html message",
- "From": "Carl Worth <cworth@cworth.org>",
- "To": "cworth@cworth.org",
- "Date": "Fri, 05 Jan 2001 15:42:57 +0000"},
- "body": [{"id": 4,
- "content-type": "multipart/alternative",
- "content": [{"id": 5,
- "content-type": "text/html",
- "content-length": 71},
- {"id": 6,
- "content-type": "text/plain",
- "content": "This is an embedded message, with a multipart/alternative part.\n"}]}]}]},
- {"id": 7,
- "content-type": "text/plain",
- "filename": "attachment",
- "content": "This is a text attachment.\n"},
- {"id": 8,
- "content-type": "text/plain",
- "content": "And this message is signed.\n\n-Carl\n"}]},
- {"id": 9,
- "content-type": "application/pgp-signature",
- "content-length": 197}]}]}}
-EOF
-test_expect_equal_json "$(cat OUTPUT)" "$(cat EXPECTED)"
-
-test_begin_subtest "'notmuch show --part' does not corrupt a part with CRLF pair"
-notmuch show --format=raw --part=3 id:base64-part-with-crlf > crlf.out
-echo -n -e "\xEF\x0D\x0A" > crlf.expected
-test_expect_equal_file crlf.out crlf.expected
-
-
-# The ISO-8859-1 encoding of U+00BD is a single byte: octal 275
-# (Portability note: Dollar-Single ($'...', ANSI C-style escape sequences)
-# quoting works on bash, ksh, zsh, *BSD sh but not on dash, ash nor busybox sh)
-readonly u_00bd_latin1=$'\275'
-
-# The Unicode fraction symbol 1/2 is U+00BD and is encoded
-# in UTF-8 as two bytes: octal 302 275
-readonly u_00bd_utf8=$'\302\275'
-
-cat <<EOF > ${MAIL_DIR}/include-html
-From: A <a@example.com>
-To: B <b@example.com>
-Subject: html message
-Date: Sat, 01 January 2000 00:00:00 +0000
-Message-ID: <htmlmessage>
-MIME-Version: 1.0
-Content-Type: multipart/alternative; boundary="==-=="
-
---==-==
-Content-Type: text/html; charset=UTF-8
-
-<p>0.5 equals ${u_00bd_utf8}</p>
-
---==-==
-Content-Type: text/html; charset=ISO-8859-1
-
-<p>0.5 equals ${u_00bd_latin1}</p>
-
---==-==
-Content-Type: text/plain; charset=UTF-8
-
-0.5 equals ${u_00bd_utf8}
-
---==-==--
-EOF
-
-notmuch new > /dev/null
-
-cat_expected_head ()
-{
- cat <<EOF
-[[[{"id": "htmlmessage", "match":true, "excluded": false, "date_relative":"2000-01-01",
- "timestamp": 946684800,
- "filename": "${MAIL_DIR}/include-html",
- "tags": ["inbox", "unread"],
- "headers": { "Date": "Sat, 01 Jan 2000 00:00:00 +0000", "From": "A <a@example.com>",
- "Subject": "html message", "To": "B <b@example.com>"},
- "body": [{
- "content-type": "multipart/alternative", "id": 1,
-EOF
-}
-
-cat_expected_head > EXPECTED.nohtml
-cat <<EOF >> EXPECTED.nohtml
-"content": [
- { "id": 2, "content-charset": "UTF-8", "content-length": 21, "content-type": "text/html"},
- { "id": 3, "content-charset": "ISO-8859-1", "content-length": 20, "content-type": "text/html"},
- { "id": 4, "content-type": "text/plain", "content": "0.5 equals \\u00bd\\n"}
-]}]},[]]]]
-EOF
-
-# Both the UTF-8 and ISO-8859-1 part should have U+00BD
-cat_expected_head > EXPECTED.withhtml
-cat <<EOF >> EXPECTED.withhtml
-"content": [
- { "id": 2, "content-type": "text/html", "content": "<p>0.5 equals \\u00bd</p>\\n"},
- { "id": 3, "content-type": "text/html", "content": "<p>0.5 equals \\u00bd</p>\\n"},
- { "id": 4, "content-type": "text/plain", "content": "0.5 equals \\u00bd\\n"}
-]}]},[]]]]
-EOF
-
-test_begin_subtest "html parts excluded by default"
-notmuch show --format=json id:htmlmessage > OUTPUT
-test_expect_equal_json "$(cat OUTPUT)" "$(cat EXPECTED.nohtml)"
-
-test_begin_subtest "html parts included"
-notmuch show --format=json --include-html id:htmlmessage > OUTPUT
-test_expect_equal_json "$(cat OUTPUT)" "$(cat EXPECTED.withhtml)"
-
-test_done
+++ /dev/null
-#!/usr/bin/env bash
-test_description='"notmuch new" in several variations'
-. ./test-lib.sh
-
-test_begin_subtest "No new messages"
-output=$(NOTMUCH_NEW)
-test_expect_equal "$output" "No new mail."
-
-
-test_begin_subtest "Single new message"
-generate_message
-output=$(NOTMUCH_NEW)
-test_expect_equal "$output" "Added 1 new message to the database."
-
-
-test_begin_subtest "Multiple new messages"
-generate_message
-generate_message
-output=$(NOTMUCH_NEW)
-test_expect_equal "$output" "Added 2 new messages to the database."
-
-
-test_begin_subtest "No new messages (non-empty DB)"
-output=$(NOTMUCH_NEW)
-test_expect_equal "$output" "No new mail."
-
-
-test_begin_subtest "New directories"
-rm -rf "${MAIL_DIR}"/* "${MAIL_DIR}"/.notmuch
-mkdir "${MAIL_DIR}"/def
-mkdir "${MAIL_DIR}"/ghi
-generate_message [dir]=def
-
-output=$(NOTMUCH_NEW)
-test_expect_equal "$output" "Added 1 new message to the database."
-
-
-test_begin_subtest "Alternate inode order"
-
-rm -rf "${MAIL_DIR}"/.notmuch
-mv "${MAIL_DIR}"/ghi "${MAIL_DIR}"/abc
-rm "${MAIL_DIR}"/def/*
-generate_message [dir]=abc
-
-output=$(NOTMUCH_NEW)
-test_expect_equal "$output" "Added 1 new message to the database."
-
-
-test_begin_subtest "Message moved in"
-rm -rf "${MAIL_DIR}"/* "${MAIL_DIR}"/.notmuch
-generate_message
-tmp_msg_filename=tmp/"$gen_msg_filename"
-mkdir -p "$(dirname "$tmp_msg_filename")"
-mv "$gen_msg_filename" "$tmp_msg_filename"
-notmuch new > /dev/null
-mv "$tmp_msg_filename" "$gen_msg_filename"
-output=$(NOTMUCH_NEW)
-test_expect_equal "$output" "Added 1 new message to the database."
-
-
-test_begin_subtest "Renamed message"
-
-generate_message
-notmuch new > /dev/null
-mv "$gen_msg_filename" "${gen_msg_filename}"-renamed
-output=$(NOTMUCH_NEW)
-test_expect_equal "$output" "No new mail. Detected 1 file rename."
-
-
-test_begin_subtest "Deleted message"
-
-rm "${gen_msg_filename}"-renamed
-output=$(NOTMUCH_NEW)
-test_expect_equal "$output" "No new mail. Removed 1 message."
-
-
-test_begin_subtest "Renamed directory"
-
-generate_message [dir]=dir
-generate_message [dir]=dir
-generate_message [dir]=dir
-
-notmuch new > /dev/null
-
-mv "${MAIL_DIR}"/dir "${MAIL_DIR}"/dir-renamed
-
-output=$(NOTMUCH_NEW)
-test_expect_equal "$output" "No new mail. Detected 3 file renames."
-
-
-test_begin_subtest "Deleted directory"
-
-rm -rf "${MAIL_DIR}"/dir-renamed
-
-output=$(NOTMUCH_NEW)
-test_expect_equal "$output" "No new mail. Removed 3 messages."
-
-
-test_begin_subtest "New directory (at end of list)"
-
-generate_message [dir]=zzz
-generate_message [dir]=zzz
-generate_message [dir]=zzz
-
-output=$(NOTMUCH_NEW)
-test_expect_equal "$output" "Added 3 new messages to the database."
-
-
-test_begin_subtest "Deleted directory (end of list)"
-
-rm -rf "${MAIL_DIR}"/zzz
-
-output=$(NOTMUCH_NEW)
-test_expect_equal "$output" "No new mail. Removed 3 messages."
-
-
-test_begin_subtest "New symlink to directory"
-
-rm -rf "${MAIL_DIR}"/.notmuch
-mv "${MAIL_DIR}" "${TMP_DIRECTORY}"/actual_maildir
-
-mkdir "${MAIL_DIR}"
-ln -s "${TMP_DIRECTORY}"/actual_maildir "${MAIL_DIR}"/symlink
-
-output=$(NOTMUCH_NEW)
-test_expect_equal "$output" "Added 1 new message to the database."
-
-
-test_begin_subtest "New symlink to a file"
-generate_message
-external_msg_filename="${TMP_DIRECTORY}"/external/"$(basename "$gen_msg_filename")"
-mkdir -p "$(dirname "$external_msg_filename")"
-mv "$gen_msg_filename" "$external_msg_filename"
-ln -s "$external_msg_filename" "$gen_msg_filename"
-output=$(NOTMUCH_NEW)
-test_expect_equal "$output" "Added 1 new message to the database."
-
-
-test_begin_subtest "Broken symlink aborts"
-ln -s does-not-exist "${MAIL_DIR}/broken"
-output=$(NOTMUCH_NEW 2>&1)
-test_expect_equal "$output" \
-"Error reading file ${MAIL_DIR}/broken: No such file or directory
-Note: A fatal error was encountered: Something went wrong trying to read or write a file
-No new mail."
-rm "${MAIL_DIR}/broken"
-
-
-test_begin_subtest "New two-level directory"
-
-generate_message [dir]=two/levels
-generate_message [dir]=two/levels
-generate_message [dir]=two/levels
-
-output=$(NOTMUCH_NEW)
-test_expect_equal "$output" "Added 3 new messages to the database."
-
-
-test_begin_subtest "Deleted two-level directory"
-
-rm -rf "${MAIL_DIR}"/two
-
-output=$(NOTMUCH_NEW)
-test_expect_equal "$output" "No new mail. Removed 3 messages."
-
-test_begin_subtest "Support single-message mbox (deprecated)"
-cat > "${MAIL_DIR}"/mbox_file1 <<EOF
-From test_suite@notmuchmail.org Fri Jan 5 15:43:57 2001
-From: Notmuch Test Suite <test_suite@notmuchmail.org>
-To: Notmuch Test Suite <test_suite@notmuchmail.org>
-Subject: Test mbox message 1
-
-Body.
-EOF
-output=$(NOTMUCH_NEW 2>&1)
-test_expect_equal "$output" \
-"Warning: ${MAIL_DIR}/mbox_file1 is an mbox containing a single message,
-likely caused by misconfigured mail delivery. Support for single-message
-mboxes is deprecated and may be removed in the future.
-Added 1 new message to the database."
-
-# This test requires that notmuch new has been run at least once.
-test_begin_subtest "Skip and report non-mail files"
-generate_message
-mkdir -p "${MAIL_DIR}"/.git && touch "${MAIL_DIR}"/.git/config
-touch "${MAIL_DIR}"/ignored_file
-touch "${MAIL_DIR}"/.ignored_hidden_file
-cat > "${MAIL_DIR}"/mbox_file <<EOF
-From test_suite@notmuchmail.org Fri Jan 5 15:43:57 2001
-From: Notmuch Test Suite <test_suite@notmuchmail.org>
-To: Notmuch Test Suite <test_suite@notmuchmail.org>
-Subject: Test mbox message 1
-
-Body.
-
-From test_suite@notmuchmail.org Fri Jan 5 15:43:57 2001
-From: Notmuch Test Suite <test_suite@notmuchmail.org>
-To: Notmuch Test Suite <test_suite@notmuchmail.org>
-Subject: Test mbox message 2
-
-Body 2.
-EOF
-output=$(NOTMUCH_NEW 2>&1)
-test_expect_equal "$output" \
-"Note: Ignoring non-mail file: ${MAIL_DIR}/.git/config
-Note: Ignoring non-mail file: ${MAIL_DIR}/.ignored_hidden_file
-Note: Ignoring non-mail file: ${MAIL_DIR}/ignored_file
-Note: Ignoring non-mail file: ${MAIL_DIR}/mbox_file
-Added 1 new message to the database."
-rm "${MAIL_DIR}"/mbox_file
-
-test_begin_subtest "Ignore files and directories specified in new.ignore"
-generate_message
-notmuch config set new.ignore .git ignored_file .ignored_hidden_file
-touch "${MAIL_DIR}"/.git # change .git's mtime for notmuch new to rescan.
-output=$(NOTMUCH_NEW 2>&1)
-test_expect_equal "$output" "Added 1 new message to the database."
-
-test_begin_subtest "Ignore files and directories specified in new.ignore (multiple occurrences)"
-notmuch config set new.ignore .git ignored_file .ignored_hidden_file
-notmuch new > /dev/null # ensure that files/folders will be printed in ASCII order.
-touch "${MAIL_DIR}"/.git # change .git's mtime for notmuch new to rescan.
-touch "${MAIL_DIR}" # likewise for MAIL_DIR
-mkdir -p "${MAIL_DIR}"/one/two/three/.git
-touch "${MAIL_DIR}"/{one,one/two,one/two/three}/ignored_file
-output=$(NOTMUCH_NEW --debug 2>&1 | sort)
-test_expect_equal "$output" \
-"(D) add_files_recursive, pass 1: explicitly ignoring ${MAIL_DIR}/.git
-(D) add_files_recursive, pass 1: explicitly ignoring ${MAIL_DIR}/.ignored_hidden_file
-(D) add_files_recursive, pass 1: explicitly ignoring ${MAIL_DIR}/ignored_file
-(D) add_files_recursive, pass 1: explicitly ignoring ${MAIL_DIR}/one/ignored_file
-(D) add_files_recursive, pass 1: explicitly ignoring ${MAIL_DIR}/one/two/ignored_file
-(D) add_files_recursive, pass 1: explicitly ignoring ${MAIL_DIR}/one/two/three/.git
-(D) add_files_recursive, pass 1: explicitly ignoring ${MAIL_DIR}/one/two/three/ignored_file
-(D) add_files_recursive, pass 2: explicitly ignoring ${MAIL_DIR}/.git
-(D) add_files_recursive, pass 2: explicitly ignoring ${MAIL_DIR}/.ignored_hidden_file
-(D) add_files_recursive, pass 2: explicitly ignoring ${MAIL_DIR}/ignored_file
-(D) add_files_recursive, pass 2: explicitly ignoring ${MAIL_DIR}/one/ignored_file
-(D) add_files_recursive, pass 2: explicitly ignoring ${MAIL_DIR}/one/two/ignored_file
-(D) add_files_recursive, pass 2: explicitly ignoring ${MAIL_DIR}/one/two/three/.git
-(D) add_files_recursive, pass 2: explicitly ignoring ${MAIL_DIR}/one/two/three/ignored_file
-No new mail."
-
-
-test_begin_subtest "Don't stop for ignored broken symlinks"
-notmuch config set new.ignore .git ignored_file .ignored_hidden_file broken_link
-ln -s i_do_not_exist "${MAIL_DIR}"/broken_link
-output=$(NOTMUCH_NEW 2>&1)
-test_expect_equal "$output" "No new mail."
-
-test_done
cd $(dirname "$0")
-TESTS="
- basic
- help-test
- compact
- config
- setup
- new
- count
- insert
- search
- search-output
- search-by-folder
- search-position-overlap-bug
- search-insufficient-from-quoting
- search-limiting
- excludes
- tagging
- json
- sexp
- text
- multipart
- thread-naming
- raw
- reply
- reply-to-sender
- dump-restore
- uuencode
- thread-order
- author-order
- from-guessing
- long-id
- encoding
- emacs
- emacs-large-search-buffer
- emacs-subject-to-filename
- maildir-sync
- crypto
- symbol-hiding
- search-folder-coherence
- atomicity
- python
- hooks
- argument-parsing
- emacs-test-functions
- emacs-address-cleaning
- emacs-hello
- emacs-show
- emacs-tree
- missing-headers
- hex-escaping
- parse-time-string
- search-date
- thread-replies
-"
-TESTS=${NOTMUCH_TESTS:=$TESTS}
+TESTS=${NOTMUCH_TESTS:-`echo T[0-9][0-9][0-9]-*.sh`}
# Clean up any results from a previous run
rm -r test-results >/dev/null 2>/dev/null
trap - HUP INT TERM
# Report results
+echo
./aggregate-results.sh test-results/*
ev=$?
+++ /dev/null
-#!/usr/bin/env bash
-test_description="date/time parser module"
-. ./test-lib.sh
-
-# Sanity/smoke tests for the date/time parser independent of notmuch
-
-_date ()
-{
- date -d "$*" +%s
-}
-
-_parse_time ()
-{
- ${TEST_DIRECTORY}/parse-time --format=%s "$*"
-}
-
-test_begin_subtest "date(1) default format without TZ code"
-test_expect_equal "$(_parse_time Fri Aug 3 23:06:06 2012)" "$(_date Fri Aug 3 23:06:06 2012)"
-
-test_begin_subtest "date(1) --rfc-2822 format"
-test_expect_equal "$(_parse_time Fri, 03 Aug 2012 23:07:46 +0100)" "$(_date Fri, 03 Aug 2012 23:07:46 +0100)"
-
-test_begin_subtest "date(1) --rfc=3339=seconds format"
-test_expect_equal "$(_parse_time 2012-08-03 23:09:37+03:00)" "$(_date 2012-08-03 23:09:37+03:00)"
-
-test_begin_subtest "Date parser tests"
-REFERENCE=$(_date Tue Jan 11 11:11:00 +0000 2011)
-cat <<EOF > INPUT
-now ==> Tue Jan 11 11:11:00 +0000 2011
-2010-1-1 ==> ERROR: DATEFORMAT
-Jan 2 ==> Sun Jan 02 11:11:00 +0000 2011
-Mon ==> Mon Jan 10 11:11:00 +0000 2011
-last Friday ==> ERROR: FORMAT
-2 hours ago ==> Tue Jan 11 09:11:00 +0000 2011
-last month ==> Sat Dec 11 11:11:00 +0000 2010
-month ago ==> Sat Dec 11 11:11:00 +0000 2010
-two mo ==> Thu Nov 11 11:11:00 +0000 2010
-3M ==> Mon Oct 11 11:11:00 +0000 2010
-4-mont ==> Sat Sep 11 11:11:00 +0000 2010
-5m ==> Tue Jan 11 11:06:00 +0000 2011
-dozen mi ==> Tue Jan 11 10:59:00 +0000 2011
-8am ==> Tue Jan 11 08:00:00 +0000 2011
-9:15 ==> Tue Jan 11 09:15:00 +0000 2011
-12:34 ==> Tue Jan 11 12:34:00 +0000 2011
-monday ==> Mon Jan 10 11:11:00 +0000 2011
-yesterday ==> Mon Jan 10 11:11:00 +0000 2011
-tomorrow ==> ERROR: KEYWORD
- ==> Tue Jan 11 11:11:00 +0000 2011 # empty string is reference time
-
-Aug 3 23:06:06 2012 ==> Fri Aug 03 23:06:06 +0000 2012 # date(1) default format without TZ code
-Fri, 03 Aug 2012 23:07:46 +0100 ==> Fri Aug 03 22:07:46 +0000 2012 # rfc-2822
-2012-08-03 23:09:37+03:00 ==> Fri Aug 03 20:09:37 +0000 2012 # rfc-3339 seconds
-
-10s ==> Tue Jan 11 11:10:50 +0000 2011
-19701223s ==> Fri May 28 10:37:17 +0000 2010
-19701223 ==> Wed Dec 23 11:11:00 +0000 1970
-
-19701223 +0100 ==> Wed Dec 23 11:11:00 +0000 1970 # Timezone is ignored without an error
-
-today ==^^> Wed Jan 12 00:00:00 +0000 2011
-today ==^> Tue Jan 11 23:59:59 +0000 2011
-today ==_> Tue Jan 11 00:00:00 +0000 2011
-
-this week ==^^> Sun Jan 16 00:00:00 +0000 2011
-this week ==^> Sat Jan 15 23:59:59 +0000 2011
-this week ==_> Sun Jan 09 00:00:00 +0000 2011
-
-two months ago ==> Thu Nov 11 11:11:00 +0000 2010
-two months ==> Thu Nov 11 11:11:00 +0000 2010
-
-@1348569850 ==> Tue Sep 25 10:44:10 +0000 2012
-@10 ==> Thu Jan 01 00:00:10 +0000 1970
-EOF
-
-${TEST_DIRECTORY}/parse-time --ref=${REFERENCE} < INPUT > OUTPUT
-test_expect_equal_file INPUT OUTPUT
-
-test_done
+++ /dev/null
-#!/usr/bin/env bash
-test_description="python bindings"
-. ./test-lib.sh
-
-add_email_corpus
-
-test_begin_subtest "compare thread ids"
-test_python <<EOF
-import notmuch
-db = notmuch.Database(mode=notmuch.Database.MODE.READ_ONLY)
-q_new = notmuch.Query(db, 'tag:inbox')
-q_new.set_sort(notmuch.Query.SORT.OLDEST_FIRST)
-for t in q_new.search_threads():
- print t.get_thread_id()
-EOF
-notmuch search --sort=oldest-first --output=threads tag:inbox | sed s/^thread:// > EXPECTED
-test_expect_equal_file OUTPUT EXPECTED
-
-test_begin_subtest "compare message ids"
-test_python <<EOF
-import notmuch
-db = notmuch.Database(mode=notmuch.Database.MODE.READ_ONLY)
-q_new = notmuch.Query(db, 'tag:inbox')
-q_new.set_sort(notmuch.Query.SORT.OLDEST_FIRST)
-for m in q_new.search_messages():
- print m.get_message_id()
-EOF
-notmuch search --sort=oldest-first --output=messages tag:inbox | sed s/^id:// > EXPECTED
-test_expect_equal_file OUTPUT EXPECTED
-
-test_begin_subtest "get non-existent file"
-test_python <<EOF
-import notmuch
-db = notmuch.Database(mode=notmuch.Database.MODE.READ_ONLY)
-print db.find_message_by_filename("i-dont-exist")
-EOF
-test_expect_equal "$(cat OUTPUT)" "None"
-
-test_done
+++ /dev/null
-#!/usr/bin/env bash
-
-test_description='notmuch show --format=raw'
-. ./test-lib.sh
-
-add_message
-add_message
-
-test_begin_subtest "Attempt to show multiple raw messages"
-output=$(notmuch show --format=raw "*" 2>&1)
-test_expect_equal "$output" "Error: search term did not match precisely one message."
-
-test_begin_subtest "Show a raw message"
-output=$(notmuch show --format=raw id:msg-001@notmuch-test-suite | notmuch_date_sanitize)
-test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@notmuchmail.org>
-To: Notmuch Test Suite <test_suite@notmuchmail.org>
-Message-Id: <msg-001@notmuch-test-suite>
-Subject: Test message #1
-Date: GENERATED_DATE
-
-This is just a test message (#1)"
-
-test_begin_subtest "Show another raw message"
-output=$(notmuch show --format=raw id:msg-002@notmuch-test-suite | notmuch_date_sanitize)
-test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@notmuchmail.org>
-To: Notmuch Test Suite <test_suite@notmuchmail.org>
-Message-Id: <msg-002@notmuch-test-suite>
-Subject: Test message #2
-Date: GENERATED_DATE
-
-This is just a test message (#2)"
-
-test_done
+++ /dev/null
-#!/usr/bin/env bash
-test_description="\"notmuch reply\" in several variations"
-. ./test-lib.sh
-
-test_begin_subtest "Basic reply"
-add_message '[from]="Sender <sender@example.com>"' \
- [to]=test_suite@notmuchmail.org \
- [subject]=notmuch-reply-test \
- '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
- '[body]="basic reply test"'
-
-output=$(notmuch reply id:${gen_msg_id})
-test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@notmuchmail.org>
-Subject: Re: notmuch-reply-test
-To: Sender <sender@example.com>
-In-Reply-To: <${gen_msg_id}>
-References: <${gen_msg_id}>
-
-On Tue, 05 Jan 2010 15:43:56 -0000, Sender <sender@example.com> wrote:
-> basic reply test"
-
-test_begin_subtest "Multiple recipients"
-add_message '[from]="Sender <sender@example.com>"' \
- '[to]="test_suite@notmuchmail.org, Someone Else <someone@example.com>"' \
- [subject]=notmuch-reply-test \
- '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
- '[body]="Multiple recipients"'
-
-output=$(notmuch reply id:${gen_msg_id})
-test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@notmuchmail.org>
-Subject: Re: notmuch-reply-test
-To: Sender <sender@example.com>, Someone Else <someone@example.com>
-In-Reply-To: <${gen_msg_id}>
-References: <${gen_msg_id}>
-
-On Tue, 05 Jan 2010 15:43:56 -0000, Sender <sender@example.com> wrote:
-> Multiple recipients"
-
-test_begin_subtest "Reply with CC"
-add_message '[from]="Sender <sender@example.com>"' \
- [to]=test_suite@notmuchmail.org \
- '[cc]="Other Parties <cc@example.com>"' \
- [subject]=notmuch-reply-test \
- '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
- '[body]="reply with CC"'
-
-output=$(notmuch reply id:${gen_msg_id})
-test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@notmuchmail.org>
-Subject: Re: notmuch-reply-test
-To: Sender <sender@example.com>
-Cc: Other Parties <cc@example.com>
-In-Reply-To: <${gen_msg_id}>
-References: <${gen_msg_id}>
-
-On Tue, 05 Jan 2010 15:43:56 -0000, Sender <sender@example.com> wrote:
-> reply with CC"
-
-test_begin_subtest "Reply from alternate address"
-add_message '[from]="Sender <sender@example.com>"' \
- [to]=test_suite_other@notmuchmail.org \
- [subject]=notmuch-reply-test \
- '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
- '[body]="reply from alternate address"'
-
-output=$(notmuch reply id:${gen_msg_id})
-test_expect_equal "$output" "From: Notmuch Test Suite <test_suite_other@notmuchmail.org>
-Subject: Re: notmuch-reply-test
-To: Sender <sender@example.com>
-In-Reply-To: <${gen_msg_id}>
-References: <${gen_msg_id}>
-
-On Tue, 05 Jan 2010 15:43:56 -0000, Sender <sender@example.com> wrote:
-> reply from alternate address"
-
-test_begin_subtest "Reply from address in named group list"
-add_message '[from]="Sender <sender@example.com>"' \
- '[to]=group:test_suite@notmuchmail.org,someone@example.com\;' \
- [cc]=test_suite_other@notmuchmail.org \
- [subject]=notmuch-reply-test \
- '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
- '[body]="Reply from address in named group list"'
-
-output=$(notmuch reply id:${gen_msg_id})
-test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@notmuchmail.org>
-Subject: Re: notmuch-reply-test
-To: Sender <sender@example.com>, someone@example.com
-In-Reply-To: <${gen_msg_id}>
-References: <${gen_msg_id}>
-
-On Tue, 05 Jan 2010 15:43:56 -0000, Sender <sender@example.com> wrote:
-> Reply from address in named group list"
-
-test_begin_subtest "Support for Reply-To"
-add_message '[from]="Sender <sender@example.com>"' \
- [to]=test_suite@notmuchmail.org \
- [subject]=notmuch-reply-test \
- '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
- '[body]="support for reply-to"' \
- '[reply-to]="Sender <elsewhere@example.com>"'
-
-output=$(notmuch reply id:${gen_msg_id})
-test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@notmuchmail.org>
-Subject: Re: notmuch-reply-test
-To: Sender <elsewhere@example.com>
-In-Reply-To: <${gen_msg_id}>
-References: <${gen_msg_id}>
-
-On Tue, 05 Jan 2010 15:43:56 -0000, Sender <sender@example.com> wrote:
-> support for reply-to"
-
-test_begin_subtest "Un-munging Reply-To"
-add_message '[from]="Sender <sender@example.com>"' \
- '[to]="Some List <list@example.com>"' \
- [subject]=notmuch-reply-test \
- '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
- '[body]="Un-munging Reply-To"' \
- '[reply-to]="Evil Munging List <list@example.com>"'
-
-output=$(notmuch reply id:${gen_msg_id})
-test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@notmuchmail.org>
-Subject: Re: notmuch-reply-test
-To: Sender <sender@example.com>, Some List <list@example.com>
-In-Reply-To: <${gen_msg_id}>
-References: <${gen_msg_id}>
-
-On Tue, 05 Jan 2010 15:43:56 -0000, Sender <sender@example.com> wrote:
-> Un-munging Reply-To"
-
-test_begin_subtest "Message with header of exactly 200 bytes"
-add_message '[subject]="This subject is exactly 200 bytes in length. Other than its length there is not much of note here. Note that the length of 200 bytes includes the Subject: and Re: prefixes with two spaces"' \
- '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
- '[body]="200-byte header"'
-output=$(notmuch reply id:${gen_msg_id})
-test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@notmuchmail.org>
-Subject: Re: This subject is exactly 200 bytes in length. Other than its
- length there is not much of note here. Note that the length of 200 bytes
- includes the Subject: and Re: prefixes with two spaces
-In-Reply-To: <${gen_msg_id}>
-References: <${gen_msg_id}>
-
-On Tue, 05 Jan 2010 15:43:56 -0000, Notmuch Test Suite <test_suite@notmuchmail.org> wrote:
-> 200-byte header"
-
-test_begin_subtest "From guessing: Envelope-To"
-add_message '[from]="Sender <sender@example.com>"' \
- '[to]="Recipient <recipient@example.com>"' \
- '[subject]="From guessing"' \
- '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
- '[body]="From guessing"' \
- '[header]="Envelope-To: test_suite_other@notmuchmail.org"'
-
-output=$(notmuch reply id:${gen_msg_id})
-test_expect_equal "$output" "From: Notmuch Test Suite <test_suite_other@notmuchmail.org>
-Subject: Re: From guessing
-To: Sender <sender@example.com>, Recipient <recipient@example.com>
-In-Reply-To: <${gen_msg_id}>
-References: <${gen_msg_id}>
-
-On Tue, 05 Jan 2010 15:43:56 -0000, Sender <sender@example.com> wrote:
-> From guessing"
-
-test_begin_subtest "From guessing: X-Original-To"
-add_message '[from]="Sender <sender@example.com>"' \
- '[to]="Recipient <recipient@example.com>"' \
- '[subject]="From guessing"' \
- '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
- '[body]="From guessing"' \
- '[header]="X-Original-To: test_suite@otherdomain.org"'
-
-output=$(notmuch reply id:${gen_msg_id})
-test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@otherdomain.org>
-Subject: Re: From guessing
-To: Sender <sender@example.com>, Recipient <recipient@example.com>
-In-Reply-To: <${gen_msg_id}>
-References: <${gen_msg_id}>
-
-On Tue, 05 Jan 2010 15:43:56 -0000, Sender <sender@example.com> wrote:
-> From guessing"
-
-test_begin_subtest "From guessing: Delivered-To"
-add_message '[from]="Sender <sender@example.com>"' \
- '[to]="Recipient <recipient@example.com>"' \
- '[subject]="From guessing"' \
- '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
- '[body]="From guessing"' \
- '[header]="Delivered-To: test_suite_other@notmuchmail.org"'
-
-output=$(notmuch reply id:${gen_msg_id})
-test_expect_equal "$output" "From: Notmuch Test Suite <test_suite_other@notmuchmail.org>
-Subject: Re: From guessing
-To: Sender <sender@example.com>, Recipient <recipient@example.com>
-In-Reply-To: <${gen_msg_id}>
-References: <${gen_msg_id}>
-
-On Tue, 05 Jan 2010 15:43:56 -0000, Sender <sender@example.com> wrote:
-> From guessing"
-
-test_begin_subtest "Reply with RFC 2047-encoded headers"
-add_message '[subject]="=?iso-8859-1?q?=e0=df=e7?="' \
- '[from]="=?utf-8?q?=e2=98=83?= <snowman@example.com>"' \
- '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
- '[body]="Encoding"'
-
-# GMime happens to change from Q- to B-encoding. We canonicalize the
-# case of the encoding and charset because different versions of GMime
-# capitalize the encoding differently.
-output=$(notmuch reply id:${gen_msg_id} | perl -pe 's/=\?[^?]+\?[bB]\?/lc($&)/ge')
-test_expect_equal "$output" "\
-From: Notmuch Test Suite <test_suite@notmuchmail.org>
-Subject: Re: =?iso-8859-1?b?4N/n?=
-To: =?utf-8?b?4piD?= <snowman@example.com>
-In-Reply-To: <${gen_msg_id}>
-References: <${gen_msg_id}>
-
-On Tue, 05 Jan 2010 15:43:56 -0000, ☃ <snowman@example.com> wrote:
-> Encoding"
-
-test_begin_subtest "Reply with RFC 2047-encoded headers (JSON)"
-output=$(notmuch reply --format=json id:${gen_msg_id})
-test_expect_equal_json "$output" '
-{
- "original": {
- "body": [
- {
- "content": "Encoding\n",
- "content-type": "text/plain",
- "id": 1
- }
- ],
- "date_relative": "2010-01-05",
- "excluded": false,
- "filename": "'${MAIL_DIR}'/msg-012",
- "headers": {
- "Date": "Tue, 05 Jan 2010 15:43:56 +0000",
- "From": "\u2603 <snowman@example.com>",
- "Subject": "\u00e0\u00df\u00e7",
- "To": "Notmuch Test Suite <test_suite@notmuchmail.org>"
- },
- "id": "'${gen_msg_id}'",
- "match": false,
- "tags": [
- "inbox",
- "unread"
- ],
- "timestamp": 1262706236
- },
- "reply-headers": {
- "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
- "In-reply-to": "<'${gen_msg_id}'>",
- "References": "<'${gen_msg_id}'>",
- "Subject": "Re: \u00e0\u00df\u00e7",
- "To": "\u2603 <snowman@example.com>"
- }
-}'
-
-
-test_done
+++ /dev/null
-#!/usr/bin/env bash
-test_description="\"notmuch reply --reply-to=sender\" in several variations"
-. ./test-lib.sh
-
-test_begin_subtest "Basic reply-to-sender"
-add_message '[from]="Sender <sender@example.com>"' \
- [to]=test_suite@notmuchmail.org \
- [subject]=notmuch-reply-test \
- '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
- '[body]="basic reply-to-sender test"'
-
-output=$(notmuch reply --reply-to=sender id:${gen_msg_id})
-test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@notmuchmail.org>
-Subject: Re: notmuch-reply-test
-To: Sender <sender@example.com>
-In-Reply-To: <${gen_msg_id}>
-References: <${gen_msg_id}>
-
-On Tue, 05 Jan 2010 15:43:56 -0000, Sender <sender@example.com> wrote:
-> basic reply-to-sender test"
-
-test_begin_subtest "From Us, Basic reply to message"
-add_message '[from]="Notmuch Test Suite <test_suite@notmuchmail.org>"' \
- '[to]="Recipient <recipient@example.com>"' \
- [subject]=notmuch-reply-test \
- '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
- '[body]="basic reply-to-from-us test"'
-
-output=$(notmuch reply --reply-to=sender id:${gen_msg_id})
-test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@notmuchmail.org>
-Subject: Re: notmuch-reply-test
-To: Recipient <recipient@example.com>
-In-Reply-To: <${gen_msg_id}>
-References: <${gen_msg_id}>
-
-On Tue, 05 Jan 2010 15:43:56 -0000, Notmuch Test Suite <test_suite@notmuchmail.org> wrote:
-> basic reply-to-from-us test"
-
-test_begin_subtest "Multiple recipients"
-add_message '[from]="Sender <sender@example.com>"' \
- '[to]="test_suite@notmuchmail.org, Someone Else <someone@example.com>"' \
- [subject]=notmuch-reply-test \
- '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
- '[body]="Multiple recipients"'
-
-output=$(notmuch reply --reply-to=sender id:${gen_msg_id})
-test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@notmuchmail.org>
-Subject: Re: notmuch-reply-test
-To: Sender <sender@example.com>
-In-Reply-To: <${gen_msg_id}>
-References: <${gen_msg_id}>
-
-On Tue, 05 Jan 2010 15:43:56 -0000, Sender <sender@example.com> wrote:
-> Multiple recipients"
-
-test_begin_subtest "From Us, Multiple TO recipients"
-add_message '[from]="Notmuch Test Suite <test_suite@notmuchmail.org>"' \
- '[to]="Recipient <recipient@example.com>, Someone Else <someone@example.com>"' \
- [subject]=notmuch-reply-test \
- '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
- '[body]="From Us, Multiple TO recipients"'
-
-output=$(notmuch reply --reply-to=sender id:${gen_msg_id})
-test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@notmuchmail.org>
-Subject: Re: notmuch-reply-test
-To: Recipient <recipient@example.com>, Someone Else <someone@example.com>
-In-Reply-To: <${gen_msg_id}>
-References: <${gen_msg_id}>
-
-On Tue, 05 Jan 2010 15:43:56 -0000, Notmuch Test Suite <test_suite@notmuchmail.org> wrote:
-> From Us, Multiple TO recipients"
-
-test_begin_subtest "Reply with CC"
-add_message '[from]="Sender <sender@example.com>"' \
- [to]=test_suite@notmuchmail.org \
- '[cc]="Other Parties <cc@example.com>"' \
- [subject]=notmuch-reply-test \
- '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
- '[body]="reply with CC"'
-
-output=$(notmuch reply --reply-to=sender id:${gen_msg_id})
-test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@notmuchmail.org>
-Subject: Re: notmuch-reply-test
-To: Sender <sender@example.com>
-In-Reply-To: <${gen_msg_id}>
-References: <${gen_msg_id}>
-
-On Tue, 05 Jan 2010 15:43:56 -0000, Sender <sender@example.com> wrote:
-> reply with CC"
-
-test_begin_subtest "From Us, Reply with CC"
-add_message '[from]="Notmuch Test Suite <test_suite@notmuchmail.org>"' \
- '[to]="Recipient <recipient@example.com>"' \
- '[cc]="Other Parties <cc@example.com>"' \
- [subject]=notmuch-reply-test \
- '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
- '[body]="reply with CC"'
-
-output=$(notmuch reply --reply-to=sender id:${gen_msg_id})
-test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@notmuchmail.org>
-Subject: Re: notmuch-reply-test
-To: Recipient <recipient@example.com>
-In-Reply-To: <${gen_msg_id}>
-References: <${gen_msg_id}>
-
-On Tue, 05 Jan 2010 15:43:56 -0000, Notmuch Test Suite <test_suite@notmuchmail.org> wrote:
-> reply with CC"
-
-test_begin_subtest "From Us, Reply no TO but with CC"
-add_message '[from]="Notmuch Test Suite <test_suite@notmuchmail.org>"' \
- '[cc]="Other Parties <cc@example.com>"' \
- [subject]=notmuch-reply-test \
- '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
- '[body]="reply with CC"'
-
-output=$(notmuch reply --reply-to=sender id:${gen_msg_id})
-test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@notmuchmail.org>
-Subject: Re: notmuch-reply-test
-Cc: Other Parties <cc@example.com>
-In-Reply-To: <${gen_msg_id}>
-References: <${gen_msg_id}>
-
-On Tue, 05 Jan 2010 15:43:56 -0000, Notmuch Test Suite <test_suite@notmuchmail.org> wrote:
-> reply with CC"
-
-test_begin_subtest "Reply from alternate address"
-add_message '[from]="Sender <sender@example.com>"' \
- [to]=test_suite_other@notmuchmail.org \
- [subject]=notmuch-reply-test \
- '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
- '[body]="reply from alternate address"'
-
-output=$(notmuch reply --reply-to=sender id:${gen_msg_id})
-test_expect_equal "$output" "From: Notmuch Test Suite <test_suite_other@notmuchmail.org>
-Subject: Re: notmuch-reply-test
-To: Sender <sender@example.com>
-In-Reply-To: <${gen_msg_id}>
-References: <${gen_msg_id}>
-
-On Tue, 05 Jan 2010 15:43:56 -0000, Sender <sender@example.com> wrote:
-> reply from alternate address"
-
-test_begin_subtest "Support for Reply-To"
-add_message '[from]="Sender <sender@example.com>"' \
- [to]=test_suite@notmuchmail.org \
- [subject]=notmuch-reply-test \
- '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
- '[body]="support for reply-to"' \
- '[reply-to]="Sender <elsewhere@example.com>"'
-
-output=$(notmuch reply --reply-to=sender id:${gen_msg_id})
-test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@notmuchmail.org>
-Subject: Re: notmuch-reply-test
-To: Sender <elsewhere@example.com>
-In-Reply-To: <${gen_msg_id}>
-References: <${gen_msg_id}>
-
-On Tue, 05 Jan 2010 15:43:56 -0000, Sender <sender@example.com> wrote:
-> support for reply-to"
-
-test_begin_subtest "Support for Reply-To with multiple recipients"
-add_message '[from]="Sender <sender@example.com>"' \
- '[to]="test_suite@notmuchmail.org, Someone Else <someone@example.com>"' \
- [subject]=notmuch-reply-test \
- '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
- '[body]="support for reply-to with multiple recipients"' \
- '[reply-to]="Sender <elsewhere@example.com>"'
-
-output=$(notmuch reply --reply-to=sender id:${gen_msg_id})
-test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@notmuchmail.org>
-Subject: Re: notmuch-reply-test
-To: Sender <elsewhere@example.com>
-In-Reply-To: <${gen_msg_id}>
-References: <${gen_msg_id}>
-
-On Tue, 05 Jan 2010 15:43:56 -0000, Sender <sender@example.com> wrote:
-> support for reply-to with multiple recipients"
-
-test_begin_subtest "Un-munging Reply-To"
-add_message '[from]="Sender <sender@example.com>"' \
- '[to]="Some List <list@example.com>"' \
- [subject]=notmuch-reply-test \
- '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
- '[body]="Un-munging Reply-To"' \
- '[reply-to]="Evil Munging List <list@example.com>"'
-
-output=$(notmuch reply --reply-to=sender id:${gen_msg_id})
-test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@notmuchmail.org>
-Subject: Re: notmuch-reply-test
-To: Sender <sender@example.com>
-In-Reply-To: <${gen_msg_id}>
-References: <${gen_msg_id}>
-
-On Tue, 05 Jan 2010 15:43:56 -0000, Sender <sender@example.com> wrote:
-> Un-munging Reply-To"
-
-test_begin_subtest "Message with header of exactly 200 bytes"
-add_message '[subject]="This subject is exactly 200 bytes in length. Other than its length there is not much of note here. Note that the length of 200 bytes includes the Subject: and Re: prefixes with two spaces"' \
- '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
- '[body]="200-byte header"'
-output=$(notmuch reply --reply-to=sender id:${gen_msg_id})
-test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@notmuchmail.org>
-Subject: Re: This subject is exactly 200 bytes in length. Other than its
- length there is not much of note here. Note that the length of 200 bytes
- includes the Subject: and Re: prefixes with two spaces
-In-Reply-To: <${gen_msg_id}>
-References: <${gen_msg_id}>
-
-On Tue, 05 Jan 2010 15:43:56 -0000, Notmuch Test Suite <test_suite@notmuchmail.org> wrote:
-> 200-byte header"
-test_done
+++ /dev/null
-#!/usr/bin/env bash
-test_description='"notmuch search" in several variations'
-. ./test-lib.sh
-
-add_email_corpus
-
-test_begin_subtest "Search body"
-add_message '[subject]="body search"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"' [body]=bodysearchtest
-output=$(notmuch search bodysearchtest | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; body search (inbox unread)"
-
-test_begin_subtest "Search by from:"
-add_message '[subject]="search by from"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"' [from]=searchbyfrom
-output=$(notmuch search from:searchbyfrom | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2000-01-01 [1/1] searchbyfrom; search by from (inbox unread)"
-
-test_begin_subtest "Search by to:"
-add_message '[subject]="search by to"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"' [to]=searchbyto
-output=$(notmuch search to:searchbyto | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; search by to (inbox unread)"
-
-test_begin_subtest "Search by subject:"
-add_message [subject]=subjectsearchtest '[date]="Sat, 01 Jan 2000 12:00:00 -0000"'
-output=$(notmuch search subject:subjectsearchtest | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; subjectsearchtest (inbox unread)"
-
-test_begin_subtest "Search by subject (utf-8):"
-add_message [subject]=utf8-sübjéct '[date]="Sat, 01 Jan 2000 12:00:00 -0000"'
-output=$(notmuch search subject:utf8-sübjéct | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; utf8-sübjéct (inbox unread)"
-
-test_begin_subtest "Search by id:"
-add_message '[subject]="search by id"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"'
-output=$(notmuch search id:${gen_msg_id} | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; search by id (inbox unread)"
-
-test_begin_subtest "Search by tag:"
-add_message '[subject]="search by tag"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"'
-notmuch tag +searchbytag id:${gen_msg_id}
-output=$(notmuch search tag:searchbytag | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; search by tag (inbox searchbytag unread)"
-
-test_begin_subtest "Search by thread:"
-add_message '[subject]="search by thread"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"'
-thread_id=$(notmuch search id:${gen_msg_id} | sed -e "s/thread:\([a-f0-9]*\).*/\1/")
-output=$(notmuch search thread:${thread_id} | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; search by thread (inbox unread)"
-
-test_begin_subtest "Search body (phrase)"
-add_message '[subject]="body search (phrase)"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"' '[body]="body search (phrase)"'
-add_message '[subject]="negative result"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"' '[body]="This phrase should not match the body search"'
-output=$(notmuch search '"body search (phrase)"' | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; body search (phrase) (inbox unread)"
-
-test_begin_subtest "Search by from: (address)"
-add_message '[subject]="search by from (address)"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"' [from]=searchbyfrom@example.com
-output=$(notmuch search from:searchbyfrom@example.com | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2000-01-01 [1/1] searchbyfrom@example.com; search by from (address) (inbox unread)"
-
-test_begin_subtest "Search by from: (name)"
-add_message '[subject]="search by from (name)"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"' '[from]="Search By From Name <test@example.com>"'
-output=$(notmuch search from:"Search By From Name" | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2000-01-01 [1/1] Search By From Name; search by from (name) (inbox unread)"
-
-test_begin_subtest "Search by to: (address)"
-add_message '[subject]="search by to (address)"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"' [to]=searchbyto@example.com
-output=$(notmuch search to:searchbyto@example.com | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; search by to (address) (inbox unread)"
-
-test_begin_subtest "Search by to: (name)"
-add_message '[subject]="search by to (name)"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"' '[to]="Search By To Name <test@example.com>"'
-output=$(notmuch search to:"Search By To Name" | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; search by to (name) (inbox unread)"
-
-test_begin_subtest "Search by subject: (phrase)"
-add_message '[subject]="subject search test (phrase)"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"'
-add_message '[subject]="this phrase should not match the subject search test"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"'
-output=$(notmuch search 'subject:"subject search test (phrase)"' | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; subject search test (phrase) (inbox unread)"
-
-test_begin_subtest 'Search for all messages ("*")'
-notmuch search '*' | notmuch_search_sanitize > OUTPUT
-cat <<EOF >EXPECTED
-thread:XXX 2010-12-29 [1/1] François Boulogne; [aur-general] Guidelines: cp, mkdir vs install (inbox unread)
-thread:XXX 2010-12-16 [1/1] Olivier Berger; Essai accentué (inbox unread)
-thread:XXX 2009-11-18 [1/1] Chris Wilson; [notmuch] [PATCH 1/2] Makefile: evaluate pkg-config once (inbox unread)
-thread:XXX 2009-11-18 [2/2] Alex Botero-Lowry, Carl Worth; [notmuch] [PATCH] Error out if no query is supplied to search instead of going into an infinite loop (attachment inbox unread)
-thread:XXX 2009-11-18 [2/2] Ingmar Vanhassel, Carl Worth; [notmuch] [PATCH] Typsos (inbox unread)
-thread:XXX 2009-11-18 [3/3] Adrian Perez de Castro, Keith Packard, Carl Worth; [notmuch] Introducing myself (inbox signed unread)
-thread:XXX 2009-11-18 [3/3] Israel Herraiz, Keith Packard, Carl Worth; [notmuch] New to the list (inbox unread)
-thread:XXX 2009-11-18 [3/3] Jan Janak, Carl Worth; [notmuch] What a great idea! (inbox unread)
-thread:XXX 2009-11-18 [2/2] Jan Janak, Carl Worth; [notmuch] [PATCH] Older versions of install do not support -C. (inbox unread)
-thread:XXX 2009-11-18 [3/3] Aron Griffis, Keith Packard, Carl Worth; [notmuch] archive (inbox unread)
-thread:XXX 2009-11-18 [2/2] Keith Packard, Carl Worth; [notmuch] [PATCH] Make notmuch-show 'X' (and 'x') commands remove inbox (and unread) tags (inbox unread)
-thread:XXX 2009-11-18 [7/7] Lars Kellogg-Stedman, Mikhail Gusarov, Keith Packard, Carl Worth; [notmuch] Working with Maildir storage? (inbox signed unread)
-thread:XXX 2009-11-18 [5/5] Mikhail Gusarov, Carl Worth, Keith Packard; [notmuch] [PATCH 1/2] Close message file after parsing message headers (inbox unread)
-thread:XXX 2009-11-18 [2/2] Keith Packard, Alexander Botero-Lowry; [notmuch] [PATCH] Create a default notmuch-show-hook that highlights URLs and uses word-wrap (inbox unread)
-thread:XXX 2009-11-18 [1/1] Alexander Botero-Lowry; [notmuch] request for pull (inbox unread)
-thread:XXX 2009-11-18 [4/4] Jjgod Jiang, Alexander Botero-Lowry; [notmuch] Mac OS X/Darwin compatibility issues (inbox unread)
-thread:XXX 2009-11-18 [1/1] Rolland Santimano; [notmuch] Link to mailing list archives ? (inbox unread)
-thread:XXX 2009-11-18 [1/1] Jan Janak; [notmuch] [PATCH] notmuch new: Support for conversion of spool subdirectories into tags (inbox unread)
-thread:XXX 2009-11-18 [1/1] Stewart Smith; [notmuch] [PATCH] count_files: sort directory in inode order before statting (inbox unread)
-thread:XXX 2009-11-18 [1/1] Stewart Smith; [notmuch] [PATCH 2/2] Read mail directory in inode number order (inbox unread)
-thread:XXX 2009-11-18 [1/1] Stewart Smith; [notmuch] [PATCH] Fix linking with gcc to use g++ to link in C++ libs. (inbox unread)
-thread:XXX 2009-11-18 [2/2] Lars Kellogg-Stedman; [notmuch] "notmuch help" outputs to stderr? (attachment inbox signed unread)
-thread:XXX 2009-11-17 [1/1] Mikhail Gusarov; [notmuch] [PATCH] Handle rename of message file (inbox unread)
-thread:XXX 2009-11-17 [2/2] Alex Botero-Lowry, Carl Worth; [notmuch] preliminary FreeBSD support (attachment inbox unread)
-thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; body search (inbox unread)
-thread:XXX 2000-01-01 [1/1] searchbyfrom; search by from (inbox unread)
-thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; search by to (inbox unread)
-thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; subjectsearchtest (inbox unread)
-thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; utf8-sübjéct (inbox unread)
-thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; search by id (inbox unread)
-thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; search by tag (inbox searchbytag unread)
-thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; search by thread (inbox unread)
-thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; body search (phrase) (inbox unread)
-thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; negative result (inbox unread)
-thread:XXX 2000-01-01 [1/1] searchbyfrom@example.com; search by from (address) (inbox unread)
-thread:XXX 2000-01-01 [1/1] Search By From Name; search by from (name) (inbox unread)
-thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; search by to (address) (inbox unread)
-thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; search by to (name) (inbox unread)
-thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; subject search test (phrase) (inbox unread)
-thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; this phrase should not match the subject search test (inbox unread)
-EOF
-test_expect_equal_file OUTPUT EXPECTED
-
-test_begin_subtest "Search body (utf-8):"
-add_message '[subject]="utf8-message-body-subject"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"' '[body]="message body utf8: bödý"'
-output=$(notmuch search "bödý" | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; utf8-message-body-subject (inbox unread)"
-
-test_done
+++ /dev/null
-#!/usr/bin/env bash
-test_description='"notmuch search" by folder: (with variations)'
-. ./test-lib.sh
-
-add_message '[dir]=bad' '[subject]="To the bone"'
-add_message '[dir]=bad/news' '[subject]="Bears"'
-mkdir -p "${MAIL_DIR}/duplicate/bad/news"
-cp "$gen_msg_filename" "${MAIL_DIR}/duplicate/bad/news"
-
-add_message '[dir]=things' '[subject]="These are a few"'
-add_message '[dir]=things/favorite' '[subject]="Raindrops, whiskers, kettles"'
-add_message '[dir]=things/bad' '[subject]="Bites, stings, sad feelings"'
-
-test_begin_subtest "Single-world folder: specification (multiple results)"
-output=$(notmuch search folder:bad | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; To the bone (inbox unread)
-thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Bears (inbox unread)
-thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Bites, stings, sad feelings (inbox unread)"
-
-test_begin_subtest "Two-word path to narrow results to one"
-output=$(notmuch search folder:bad/news | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Bears (inbox unread)"
-
-test_begin_subtest "After removing duplicate instance of matching path"
-rm -r "${MAIL_DIR}/bad/news"
-notmuch new
-output=$(notmuch search folder:bad/news | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Bears (inbox unread)"
-
-test_begin_subtest "After rename, old path returns nothing"
-mv "${MAIL_DIR}/duplicate/bad/news" "${MAIL_DIR}/duplicate/bad/olds"
-notmuch new
-output=$(notmuch search folder:bad/news | notmuch_search_sanitize)
-test_expect_equal "$output" ""
-
-test_begin_subtest "After rename, new path returns result"
-output=$(notmuch search folder:bad/olds | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Bears (inbox unread)"
-
-test_done
+++ /dev/null
-#!/usr/bin/env bash
-test_description="date:since..until queries"
-. ./test-lib.sh
-
-add_email_corpus
-
-test_begin_subtest "Absolute date range"
-output=$(notmuch search date:2010-12-16..12/16/2010 | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2010-12-16 [1/1] Olivier Berger; Essai accentué (inbox unread)"
-
-test_begin_subtest "Absolute time range with TZ"
-notmuch search date:18-Nov-2009_02:19:26-0800..2009-11-18_04:49:52-06:00 | notmuch_search_sanitize > OUTPUT
-cat <<EOF >EXPECTED
-thread:XXX 2009-11-18 [1/3] Carl Worth| Jan Janak; [notmuch] What a great idea! (inbox unread)
-thread:XXX 2009-11-18 [1/2] Carl Worth| Jan Janak; [notmuch] [PATCH] Older versions of install do not support -C. (inbox unread)
-thread:XXX 2009-11-18 [1/3] Carl Worth| Aron Griffis, Keith Packard; [notmuch] archive (inbox unread)
-thread:XXX 2009-11-18 [1/2] Carl Worth| Keith Packard; [notmuch] [PATCH] Make notmuch-show 'X' (and 'x') commands remove inbox (and unread) tags (inbox unread)
-EOF
-test_expect_equal_file OUTPUT EXPECTED
-
-test_done
+++ /dev/null
-#!/usr/bin/env bash
-test_description='folder tags removed and added through file renames remain consistent'
-. ./test-lib.sh
-
-test_begin_subtest "No new messages"
-output=$(NOTMUCH_NEW)
-test_expect_equal "$output" "No new mail."
-
-
-test_begin_subtest "Single new message"
-generate_message
-file_x=$gen_msg_filename
-id_x=$gen_msg_id
-output=$(NOTMUCH_NEW)
-test_expect_equal "$output" "Added 1 new message to the database."
-
-test_begin_subtest "Add second folder for same message"
-dir=$(dirname $file_x)
-mkdir $dir/spam
-cp $file_x $dir/spam
-output=$(NOTMUCH_NEW)
-test_expect_equal "$output" "No new mail."
-
-
-test_begin_subtest "Multiple files for same message"
-cat <<EOF >EXPECTED
-MAIL_DIR/msg-001
-MAIL_DIR/spam/msg-001
-EOF
-notmuch search --output=files id:$id_x | sed -e "s,$MAIL_DIR,MAIL_DIR," >OUTPUT
-test_expect_equal_file OUTPUT EXPECTED
-
-test_begin_subtest "Test matches folder:spam"
-output=$(notmuch search folder:spam)
-test_expect_equal "$output" "thread:0000000000000001 2001-01-05 [1/1] Notmuch Test Suite; Single new message (inbox unread)"
-
-test_begin_subtest "Remove folder:spam copy of email"
-rm $dir/spam/$(basename $file_x)
-output=$(NOTMUCH_NEW)
-test_expect_equal "$output" "No new mail. Detected 1 file rename."
-
-test_begin_subtest "No mails match the folder:spam search"
-output=$(notmuch search folder:spam)
-test_expect_equal "$output" ""
-
-test_done
+++ /dev/null
-#!/usr/bin/env bash
-test_description='messages with unquoted . in name'
-. ./test-lib.sh
-
-add_message \
- '[from]="Some.Name for Someone <bugs@quoting.com>"' \
- '[subject]="This message needs more quoting on the From line"'
-
-add_message \
- '[from]="\"Some.Name for Someone\" <bugs@quoting.com>"' \
- '[subject]="This message has necessary quoting in place"'
-
-add_message \
- '[from]="No.match Here <filler@mail.com>"' \
- '[subject]="This message needs more quoting on the From line"'
-
-add_message \
- '[from]="\"No.match Here\" <filler@mail.com>"' \
- '[subject]="This message has necessary quoting in place"'
-
-
-test_begin_subtest "Search by first name"
-output=$(notmuch search from:Some.Name | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Some.Name for Someone; This message needs more quoting on the From line (inbox unread)
-thread:XXX 2001-01-05 [1/1] Some.Name for Someone; This message has necessary quoting in place (inbox unread)"
-
-test_begin_subtest "Search by last name:"
-output=$(notmuch search from:Someone | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Some.Name for Someone; This message needs more quoting on the From line (inbox unread)
-thread:XXX 2001-01-05 [1/1] Some.Name for Someone; This message has necessary quoting in place (inbox unread)"
-
-test_begin_subtest "Search by address:"
-output=$(notmuch search from:bugs@quoting.com | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Some.Name for Someone; This message needs more quoting on the From line (inbox unread)
-thread:XXX 2001-01-05 [1/1] Some.Name for Someone; This message has necessary quoting in place (inbox unread)"
-
-test_begin_subtest "Search for all messages:"
-output=$(notmuch search '*' | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Some.Name for Someone; This message needs more quoting on the From line (inbox unread)
-thread:XXX 2001-01-05 [1/1] Some.Name for Someone; This message has necessary quoting in place (inbox unread)
-thread:XXX 2001-01-05 [1/1] No.match Here; This message needs more quoting on the From line (inbox unread)
-thread:XXX 2001-01-05 [1/1] No.match Here; This message has necessary quoting in place (inbox unread)"
-
-test_done
+++ /dev/null
-#!/usr/bin/env bash
-test_description='"notmuch search" --offset and --limit parameters'
-. ./test-lib.sh
-
-add_email_corpus
-
-for outp in messages threads; do
- test_begin_subtest "${outp}: limit does the right thing"
- notmuch search --output=${outp} "*" | head -n 20 >expected
- notmuch search --output=${outp} --limit=20 "*" >output
- test_expect_equal_file expected output
-
- test_begin_subtest "${outp}: concatenation of limited searches"
- notmuch search --output=${outp} "*" | head -n 20 >expected
- notmuch search --output=${outp} --limit=10 "*" >output
- notmuch search --output=${outp} --limit=10 --offset=10 "*" >>output
- test_expect_equal_file expected output
-
- test_begin_subtest "${outp}: limit larger than result set"
- N=`notmuch count --output=${outp} "*"`
- notmuch search --output=${outp} "*" >expected
- notmuch search --output=${outp} --limit=$((1 + ${N})) "*" >output
- test_expect_equal_file expected output
-
- test_begin_subtest "${outp}: limit = 0"
- test_expect_equal "`notmuch search --output=${outp} --limit=0 "*"`" ""
-
- test_begin_subtest "${outp}: offset does the right thing"
- # note: tail -n +N is 1-based
- notmuch search --output=${outp} "*" | tail -n +21 >expected
- notmuch search --output=${outp} --offset=20 "*" >output
- test_expect_equal_file expected output
-
- test_begin_subtest "${outp}: offset = 0"
- notmuch search --output=${outp} "*" >expected
- notmuch search --output=${outp} --offset=0 "*" >output
- test_expect_equal_file expected output
-
- test_begin_subtest "${outp}: negative offset"
- notmuch search --output=${outp} "*" | tail -n 20 >expected
- notmuch search --output=${outp} --offset=-20 "*" >output
- test_expect_equal_file expected output
-
- test_begin_subtest "${outp}: negative offset"
- notmuch search --output=${outp} "*" | tail -n 1 >expected
- notmuch search --output=${outp} --offset=-1 "*" >output
- test_expect_equal_file expected output
-
- test_begin_subtest "${outp}: negative offset combined with limit"
- notmuch search --output=${outp} "*" | tail -n 20 | head -n 10 >expected
- notmuch search --output=${outp} --offset=-20 --limit=10 "*" >output
- test_expect_equal_file expected output
-
- test_begin_subtest "${outp}: negative offset combined with equal limit"
- notmuch search --output=${outp} "*" | tail -n 20 >expected
- notmuch search --output=${outp} --offset=-20 --limit=20 "*" >output
- test_expect_equal_file expected output
-
- test_begin_subtest "${outp}: negative offset combined with large limit"
- notmuch search --output=${outp} "*" | tail -n 20 >expected
- notmuch search --output=${outp} --offset=-20 --limit=50 "*" >output
- test_expect_equal_file expected output
-
- test_begin_subtest "${outp}: negative offset larger then results"
- N=`notmuch count --output=${outp} "*"`
- notmuch search --output=${outp} "*" >expected
- notmuch search --output=${outp} --offset=-$((1 + ${N})) "*" >output
- test_expect_equal_file expected output
-done
-
-test_done
+++ /dev/null
-#!/usr/bin/env bash
-test_description='various settings for "notmuch search --output="'
-. ./test-lib.sh
-
-add_email_corpus
-
-test_begin_subtest "--output=threads"
-notmuch search --output=threads '*' | sed -e s/thread:.*/thread:THREADID/ >OUTPUT
-cat <<EOF >EXPECTED
-thread:THREADID
-thread:THREADID
-thread:THREADID
-thread:THREADID
-thread:THREADID
-thread:THREADID
-thread:THREADID
-thread:THREADID
-thread:THREADID
-thread:THREADID
-thread:THREADID
-thread:THREADID
-thread:THREADID
-thread:THREADID
-thread:THREADID
-thread:THREADID
-thread:THREADID
-thread:THREADID
-thread:THREADID
-thread:THREADID
-thread:THREADID
-thread:THREADID
-thread:THREADID
-thread:THREADID
-EOF
-test_expect_equal_file OUTPUT EXPECTED
-
-test_begin_subtest "--output=threads --format=json"
-notmuch search --format=json --output=threads '*' | sed -e s/\".*\"/\"THREADID\"/ >OUTPUT
-cat <<EOF >EXPECTED
-["THREADID",
-"THREADID",
-"THREADID",
-"THREADID",
-"THREADID",
-"THREADID",
-"THREADID",
-"THREADID",
-"THREADID",
-"THREADID",
-"THREADID",
-"THREADID",
-"THREADID",
-"THREADID",
-"THREADID",
-"THREADID",
-"THREADID",
-"THREADID",
-"THREADID",
-"THREADID",
-"THREADID",
-"THREADID",
-"THREADID",
-"THREADID"]
-EOF
-test_expect_equal_json "$(cat OUTPUT)" "$(cat EXPECTED)"
-
-test_begin_subtest "--output=messages"
-notmuch search --output=messages '*' >OUTPUT
-cat <<EOF >EXPECTED
-id:4EFC743A.3060609@april.org
-id:877h1wv7mg.fsf@inf-8657.int-evry.fr
-id:1258544095-16616-1-git-send-email-chris@chris-wilson.co.uk
-id:877htoqdbo.fsf@yoom.home.cworth.org
-id:878we4qdqf.fsf@yoom.home.cworth.org
-id:87aaykqe24.fsf@yoom.home.cworth.org
-id:87bpj0qeng.fsf@yoom.home.cworth.org
-id:87fx8cqf8v.fsf@yoom.home.cworth.org
-id:87hbssqfix.fsf@yoom.home.cworth.org
-id:87iqd8qgiz.fsf@yoom.home.cworth.org
-id:87k4xoqgnl.fsf@yoom.home.cworth.org
-id:87ocn0qh6d.fsf@yoom.home.cworth.org
-id:87pr7gqidx.fsf@yoom.home.cworth.org
-id:867hto2p0t.fsf@fortitudo.i-did-not-set--mail-host-address--so-tickle-me
-id:1258532999-9316-1-git-send-email-keithp@keithp.com
-id:86aayk2rbj.fsf@fortitudo.i-did-not-set--mail-host-address--so-tickle-me
-id:86d43g2w3y.fsf@fortitudo.i-did-not-set--mail-host-address--so-tickle-me
-id:ddd65cda0911172214t60d22b63hcfeb5a19ab54a39b@mail.gmail.com
-id:86einw2xof.fsf@fortitudo.i-did-not-set--mail-host-address--so-tickle-me
-id:736613.51770.qm@web113505.mail.gq1.yahoo.com
-id:1258520223-15328-1-git-send-email-jan@ryngle.com
-id:ddd65cda0911171950o4eea4389v86de9525e46052d3@mail.gmail.com
-id:1258510940-7018-1-git-send-email-stewart@flamingspork.com
-id:yunzl6kd1w0.fsf@aiko.keithp.com
-id:yun1vjwegii.fsf@aiko.keithp.com
-id:yun3a4cegoa.fsf@aiko.keithp.com
-id:1258509400-32511-1-git-send-email-stewart@flamingspork.com
-id:1258506353-20352-1-git-send-email-stewart@flamingspork.com
-id:20091118010116.GC25380@dottiness.seas.harvard.edu
-id:20091118005829.GB25380@dottiness.seas.harvard.edu
-id:20091118005040.GA25380@dottiness.seas.harvard.edu
-id:cf0c4d610911171623q3e27a0adx802e47039b57604b@mail.gmail.com
-id:1258500222-32066-1-git-send-email-ingmar@exherbo.org
-id:20091117232137.GA7669@griffis1.net
-id:20091118002059.067214ed@hikari
-id:1258498485-sup-142@elly
-id:f35dbb950911171438k5df6eb56k77b6c0944e2e79ae@mail.gmail.com
-id:f35dbb950911171435ieecd458o853c873e35f4be95@mail.gmail.com
-id:1258496327-12086-1-git-send-email-jan@ryngle.com
-id:1258493565-13508-1-git-send-email-keithp@keithp.com
-id:yunaayketfm.fsf@aiko.keithp.com
-id:yunbpj0etua.fsf@aiko.keithp.com
-id:1258491078-29658-1-git-send-email-dottedmag@dottedmag.net
-id:87fx8can9z.fsf@vertex.dottedmag
-id:20091117203301.GV3165@dottiness.seas.harvard.edu
-id:87lji4lx9v.fsf@yoom.home.cworth.org
-id:cf0c4d610911171136h1713aa59w9cf9aa31f052ad0a@mail.gmail.com
-id:87iqd9rn3l.fsf@vertex.dottedmag
-id:20091117190054.GU3165@dottiness.seas.harvard.edu
-id:87lji5cbwo.fsf@yoom.home.cworth.org
-id:1258471718-6781-2-git-send-email-dottedmag@dottedmag.net
-id:1258471718-6781-1-git-send-email-dottedmag@dottedmag.net
-EOF
-test_expect_equal_file OUTPUT EXPECTED
-
-test_begin_subtest "--output=messages --format=json"
-notmuch search --format=json --output=messages '*' >OUTPUT
-cat <<EOF >EXPECTED
-["4EFC743A.3060609@april.org",
-"877h1wv7mg.fsf@inf-8657.int-evry.fr",
-"1258544095-16616-1-git-send-email-chris@chris-wilson.co.uk",
-"877htoqdbo.fsf@yoom.home.cworth.org",
-"878we4qdqf.fsf@yoom.home.cworth.org",
-"87aaykqe24.fsf@yoom.home.cworth.org",
-"87bpj0qeng.fsf@yoom.home.cworth.org",
-"87fx8cqf8v.fsf@yoom.home.cworth.org",
-"87hbssqfix.fsf@yoom.home.cworth.org",
-"87iqd8qgiz.fsf@yoom.home.cworth.org",
-"87k4xoqgnl.fsf@yoom.home.cworth.org",
-"87ocn0qh6d.fsf@yoom.home.cworth.org",
-"87pr7gqidx.fsf@yoom.home.cworth.org",
-"867hto2p0t.fsf@fortitudo.i-did-not-set--mail-host-address--so-tickle-me",
-"1258532999-9316-1-git-send-email-keithp@keithp.com",
-"86aayk2rbj.fsf@fortitudo.i-did-not-set--mail-host-address--so-tickle-me",
-"86d43g2w3y.fsf@fortitudo.i-did-not-set--mail-host-address--so-tickle-me",
-"ddd65cda0911172214t60d22b63hcfeb5a19ab54a39b@mail.gmail.com",
-"86einw2xof.fsf@fortitudo.i-did-not-set--mail-host-address--so-tickle-me",
-"736613.51770.qm@web113505.mail.gq1.yahoo.com",
-"1258520223-15328-1-git-send-email-jan@ryngle.com",
-"ddd65cda0911171950o4eea4389v86de9525e46052d3@mail.gmail.com",
-"1258510940-7018-1-git-send-email-stewart@flamingspork.com",
-"yunzl6kd1w0.fsf@aiko.keithp.com",
-"yun1vjwegii.fsf@aiko.keithp.com",
-"yun3a4cegoa.fsf@aiko.keithp.com",
-"1258509400-32511-1-git-send-email-stewart@flamingspork.com",
-"1258506353-20352-1-git-send-email-stewart@flamingspork.com",
-"20091118010116.GC25380@dottiness.seas.harvard.edu",
-"20091118005829.GB25380@dottiness.seas.harvard.edu",
-"20091118005040.GA25380@dottiness.seas.harvard.edu",
-"cf0c4d610911171623q3e27a0adx802e47039b57604b@mail.gmail.com",
-"1258500222-32066-1-git-send-email-ingmar@exherbo.org",
-"20091117232137.GA7669@griffis1.net",
-"20091118002059.067214ed@hikari",
-"1258498485-sup-142@elly",
-"f35dbb950911171438k5df6eb56k77b6c0944e2e79ae@mail.gmail.com",
-"f35dbb950911171435ieecd458o853c873e35f4be95@mail.gmail.com",
-"1258496327-12086-1-git-send-email-jan@ryngle.com",
-"1258493565-13508-1-git-send-email-keithp@keithp.com",
-"yunaayketfm.fsf@aiko.keithp.com",
-"yunbpj0etua.fsf@aiko.keithp.com",
-"1258491078-29658-1-git-send-email-dottedmag@dottedmag.net",
-"87fx8can9z.fsf@vertex.dottedmag",
-"20091117203301.GV3165@dottiness.seas.harvard.edu",
-"87lji4lx9v.fsf@yoom.home.cworth.org",
-"cf0c4d610911171136h1713aa59w9cf9aa31f052ad0a@mail.gmail.com",
-"87iqd9rn3l.fsf@vertex.dottedmag",
-"20091117190054.GU3165@dottiness.seas.harvard.edu",
-"87lji5cbwo.fsf@yoom.home.cworth.org",
-"1258471718-6781-2-git-send-email-dottedmag@dottedmag.net",
-"1258471718-6781-1-git-send-email-dottedmag@dottedmag.net"]
-EOF
-test_expect_equal_file OUTPUT EXPECTED
-
-test_begin_subtest "--output=files"
-notmuch search --output=files '*' | sed -e "s,$MAIL_DIR,MAIL_DIR," >OUTPUT
-cat <<EOF >EXPECTED
-MAIL_DIR/cur/52:2,
-MAIL_DIR/cur/53:2,
-MAIL_DIR/cur/50:2,
-MAIL_DIR/cur/49:2,
-MAIL_DIR/cur/48:2,
-MAIL_DIR/cur/47:2,
-MAIL_DIR/cur/46:2,
-MAIL_DIR/cur/45:2,
-MAIL_DIR/cur/44:2,
-MAIL_DIR/cur/43:2,
-MAIL_DIR/cur/42:2,
-MAIL_DIR/cur/41:2,
-MAIL_DIR/cur/40:2,
-MAIL_DIR/cur/39:2,
-MAIL_DIR/cur/38:2,
-MAIL_DIR/cur/37:2,
-MAIL_DIR/cur/36:2,
-MAIL_DIR/cur/35:2,
-MAIL_DIR/cur/34:2,
-MAIL_DIR/cur/33:2,
-MAIL_DIR/cur/32:2,
-MAIL_DIR/cur/31:2,
-MAIL_DIR/cur/30:2,
-MAIL_DIR/cur/29:2,
-MAIL_DIR/cur/28:2,
-MAIL_DIR/cur/27:2,
-MAIL_DIR/cur/26:2,
-MAIL_DIR/cur/25:2,
-MAIL_DIR/cur/24:2,
-MAIL_DIR/cur/23:2,
-MAIL_DIR/cur/22:2,
-MAIL_DIR/cur/21:2,
-MAIL_DIR/cur/19:2,
-MAIL_DIR/cur/18:2,
-MAIL_DIR/cur/51:2,
-MAIL_DIR/cur/20:2,
-MAIL_DIR/cur/17:2,
-MAIL_DIR/cur/16:2,
-MAIL_DIR/cur/15:2,
-MAIL_DIR/cur/14:2,
-MAIL_DIR/cur/13:2,
-MAIL_DIR/cur/12:2,
-MAIL_DIR/cur/11:2,
-MAIL_DIR/cur/10:2,
-MAIL_DIR/cur/09:2,
-MAIL_DIR/cur/08:2,
-MAIL_DIR/cur/06:2,
-MAIL_DIR/cur/05:2,
-MAIL_DIR/cur/04:2,
-MAIL_DIR/cur/03:2,
-MAIL_DIR/cur/07:2,
-MAIL_DIR/cur/02:2,
-MAIL_DIR/cur/01:2,
-EOF
-test_expect_equal_file OUTPUT EXPECTED
-
-test_begin_subtest "--output=files --duplicate=1"
-notmuch search --output=files --duplicate=1 '*' | sed -e "s,$MAIL_DIR,MAIL_DIR," >OUTPUT
-cat <<EOF >EXPECTED
-MAIL_DIR/cur/52:2,
-MAIL_DIR/cur/53:2,
-MAIL_DIR/cur/50:2,
-MAIL_DIR/cur/49:2,
-MAIL_DIR/cur/48:2,
-MAIL_DIR/cur/47:2,
-MAIL_DIR/cur/46:2,
-MAIL_DIR/cur/45:2,
-MAIL_DIR/cur/44:2,
-MAIL_DIR/cur/43:2,
-MAIL_DIR/cur/42:2,
-MAIL_DIR/cur/41:2,
-MAIL_DIR/cur/40:2,
-MAIL_DIR/cur/39:2,
-MAIL_DIR/cur/38:2,
-MAIL_DIR/cur/37:2,
-MAIL_DIR/cur/36:2,
-MAIL_DIR/cur/35:2,
-MAIL_DIR/cur/34:2,
-MAIL_DIR/cur/33:2,
-MAIL_DIR/cur/32:2,
-MAIL_DIR/cur/31:2,
-MAIL_DIR/cur/30:2,
-MAIL_DIR/cur/29:2,
-MAIL_DIR/cur/28:2,
-MAIL_DIR/cur/27:2,
-MAIL_DIR/cur/26:2,
-MAIL_DIR/cur/25:2,
-MAIL_DIR/cur/24:2,
-MAIL_DIR/cur/23:2,
-MAIL_DIR/cur/22:2,
-MAIL_DIR/cur/21:2,
-MAIL_DIR/cur/19:2,
-MAIL_DIR/cur/18:2,
-MAIL_DIR/cur/20:2,
-MAIL_DIR/cur/17:2,
-MAIL_DIR/cur/16:2,
-MAIL_DIR/cur/15:2,
-MAIL_DIR/cur/14:2,
-MAIL_DIR/cur/13:2,
-MAIL_DIR/cur/12:2,
-MAIL_DIR/cur/11:2,
-MAIL_DIR/cur/10:2,
-MAIL_DIR/cur/09:2,
-MAIL_DIR/cur/08:2,
-MAIL_DIR/cur/06:2,
-MAIL_DIR/cur/05:2,
-MAIL_DIR/cur/04:2,
-MAIL_DIR/cur/03:2,
-MAIL_DIR/cur/07:2,
-MAIL_DIR/cur/02:2,
-MAIL_DIR/cur/01:2,
-EOF
-test_expect_equal_file OUTPUT EXPECTED
-
-test_begin_subtest "--output=files --format=json"
-notmuch search --format=json --output=files '*' | sed -e "s,$MAIL_DIR,MAIL_DIR," >OUTPUT
-cat <<EOF >EXPECTED
-["MAIL_DIR/cur/52:2,",
-"MAIL_DIR/cur/53:2,",
-"MAIL_DIR/cur/50:2,",
-"MAIL_DIR/cur/49:2,",
-"MAIL_DIR/cur/48:2,",
-"MAIL_DIR/cur/47:2,",
-"MAIL_DIR/cur/46:2,",
-"MAIL_DIR/cur/45:2,",
-"MAIL_DIR/cur/44:2,",
-"MAIL_DIR/cur/43:2,",
-"MAIL_DIR/cur/42:2,",
-"MAIL_DIR/cur/41:2,",
-"MAIL_DIR/cur/40:2,",
-"MAIL_DIR/cur/39:2,",
-"MAIL_DIR/cur/38:2,",
-"MAIL_DIR/cur/37:2,",
-"MAIL_DIR/cur/36:2,",
-"MAIL_DIR/cur/35:2,",
-"MAIL_DIR/cur/34:2,",
-"MAIL_DIR/cur/33:2,",
-"MAIL_DIR/cur/32:2,",
-"MAIL_DIR/cur/31:2,",
-"MAIL_DIR/cur/30:2,",
-"MAIL_DIR/cur/29:2,",
-"MAIL_DIR/cur/28:2,",
-"MAIL_DIR/cur/27:2,",
-"MAIL_DIR/cur/26:2,",
-"MAIL_DIR/cur/25:2,",
-"MAIL_DIR/cur/24:2,",
-"MAIL_DIR/cur/23:2,",
-"MAIL_DIR/cur/22:2,",
-"MAIL_DIR/cur/21:2,",
-"MAIL_DIR/cur/19:2,",
-"MAIL_DIR/cur/18:2,",
-"MAIL_DIR/cur/51:2,",
-"MAIL_DIR/cur/20:2,",
-"MAIL_DIR/cur/17:2,",
-"MAIL_DIR/cur/16:2,",
-"MAIL_DIR/cur/15:2,",
-"MAIL_DIR/cur/14:2,",
-"MAIL_DIR/cur/13:2,",
-"MAIL_DIR/cur/12:2,",
-"MAIL_DIR/cur/11:2,",
-"MAIL_DIR/cur/10:2,",
-"MAIL_DIR/cur/09:2,",
-"MAIL_DIR/cur/08:2,",
-"MAIL_DIR/cur/06:2,",
-"MAIL_DIR/cur/05:2,",
-"MAIL_DIR/cur/04:2,",
-"MAIL_DIR/cur/03:2,",
-"MAIL_DIR/cur/07:2,",
-"MAIL_DIR/cur/02:2,",
-"MAIL_DIR/cur/01:2,"]
-EOF
-test_expect_equal_file OUTPUT EXPECTED
-
-test_begin_subtest "--output=files --format=json --duplicate=2"
-notmuch search --format=json --output=files --duplicate=2 '*' | sed -e "s,$MAIL_DIR,MAIL_DIR," >OUTPUT
-cat <<EOF >EXPECTED
-["MAIL_DIR/cur/51:2,"]
-EOF
-test_expect_equal_file OUTPUT EXPECTED
-
-test_begin_subtest "--output=tags"
-notmuch search --output=tags '*' >OUTPUT
-cat <<EOF >EXPECTED
-attachment
-inbox
-signed
-unread
-EOF
-test_expect_equal_file OUTPUT EXPECTED
-
-test_begin_subtest "--output=tags --format=json"
-notmuch search --format=json --output=tags '*' >OUTPUT
-cat <<EOF >EXPECTED
-["attachment",
-"inbox",
-"signed",
-"unread"]
-EOF
-test_expect_equal_file OUTPUT EXPECTED
-
-test_begin_subtest "sanitize output for quoted-printable line-breaks in author and subject"
-add_message "[subject]='two =?ISO-8859-1?Q?line=0A_subject?=
- headers'"
-notmuch search id:"$gen_msg_id" | notmuch_search_sanitize >OUTPUT
-cat <<EOF >EXPECTED
-thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; two line? subject headers (inbox unread)
-EOF
-test_expect_equal_file OUTPUT EXPECTED
-
-test_begin_subtest "search for non-existent message prints nothing"
-notmuch search "no-message-matches-this" > OUTPUT
-echo -n >EXPECTED
-test_expect_equal_file OUTPUT EXPECTED
-
-test_begin_subtest "search --format=json for non-existent message prints proper empty json"
-notmuch search --format=json "no-message-matches-this" > OUTPUT
-echo "[]" >EXPECTED
-test_expect_equal_file OUTPUT EXPECTED
-
-test_done
+++ /dev/null
-#!/usr/bin/env bash
-
-# Test to demonstrate a position overlap bug.
-#
-# At one point, notmuch would index terms incorrectly in the case of
-# calling index_terms multiple times for a single field. The term
-# generator was being reset to position 0 each time. This means that
-# with text such as:
-#
-# To: a@b.c, x@y.z
-#
-# one could get a bogus match by searching for:
-#
-# To: a@y.c
-#
-# Thanks to Mark Anderson for reporting the bug, (and providing a nice,
-# minimal test case that inspired what is used here), in
-# id:3wd4o8wa7fx.fsf@testarossa.amd.com
-
-test_description='that notmuch does not overlap term positions'
-. ./test-lib.sh
-
-add_message '[to]="a@b.c, x@y.z"'
-
-test_begin_subtest "Search for a@b.c matches"
-output=$(notmuch search a@b.c | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Test message #1 (inbox unread)"
-
-test_begin_subtest "Search for x@y.z matches"
-output=$(notmuch search x@y.z | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Test message #1 (inbox unread)"
-
-test_begin_subtest "Search for a@y.c must not match"
-output=$(notmuch search a@y.c | notmuch_search_sanitize)
-test_expect_equal "$output" ""
-
-test_done
+++ /dev/null
-#!/usr/bin/env bash
-
-test_description='"notmuch setup"'
-. ./test-lib.sh
-
-test_begin_subtest "Create a new config interactively"
-notmuch --config=new-notmuch-config > /dev/null <<EOF
-Test Suite
-test.suite@example.com
-another.suite@example.com
-
-/path/to/maildir
-foo bar
-baz
-EOF
-output=$(notmuch --config=new-notmuch-config config list)
-test_expect_equal "$output" "\
-database.path=/path/to/maildir
-user.name=Test Suite
-user.primary_email=test.suite@example.com
-user.other_email=another.suite@example.com;
-new.tags=foo;bar;
-new.ignore=
-search.exclude_tags=baz;
-maildir.synchronize_flags=true"
-
-test_done
+++ /dev/null
-#!/usr/bin/env bash
-test_description="--format=sexp output"
-. ./test-lib.sh
-
-test_begin_subtest "Show message: sexp"
-add_message "[subject]=\"sexp-show-subject\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[bcc]=\"test_suite+bcc@notmuchmail.org\"" "[reply-to]=\"test_suite+replyto@notmuchmail.org\"" "[body]=\"sexp-show-message\""
-output=$(notmuch show --format=sexp "sexp-show-message")
-test_expect_equal "$output" "((((:id \"${gen_msg_id}\" :match t :excluded nil :filename \"${gen_msg_filename}\" :timestamp 946728000 :date_relative \"2000-01-01\" :tags (\"inbox\" \"unread\") :headers (:Subject \"sexp-show-subject\" :From \"Notmuch Test Suite <test_suite@notmuchmail.org>\" :To \"Notmuch Test Suite <test_suite@notmuchmail.org>\" :Bcc \"test_suite+bcc@notmuchmail.org\" :Reply-To \"test_suite+replyto@notmuchmail.org\" :Date \"Sat, 01 Jan 2000 12:00:00 +0000\") :body ((:id 1 :content-type \"text/plain\" :content \"sexp-show-message\n\"))) ())))"
-
-# This should be the same output as above.
-test_begin_subtest "Show message: sexp --body=true"
-output=$(notmuch show --format=sexp --body=true "sexp-show-message")
-test_expect_equal "$output" "((((:id \"${gen_msg_id}\" :match t :excluded nil :filename \"${gen_msg_filename}\" :timestamp 946728000 :date_relative \"2000-01-01\" :tags (\"inbox\" \"unread\") :headers (:Subject \"sexp-show-subject\" :From \"Notmuch Test Suite <test_suite@notmuchmail.org>\" :To \"Notmuch Test Suite <test_suite@notmuchmail.org>\" :Bcc \"test_suite+bcc@notmuchmail.org\" :Reply-To \"test_suite+replyto@notmuchmail.org\" :Date \"Sat, 01 Jan 2000 12:00:00 +0000\") :body ((:id 1 :content-type \"text/plain\" :content \"sexp-show-message\n\"))) ())))"
-
-test_begin_subtest "Show message: sexp --body=false"
-output=$(notmuch show --format=sexp --body=false "sexp-show-message")
-test_expect_equal "$output" "((((:id \"${gen_msg_id}\" :match t :excluded nil :filename \"${gen_msg_filename}\" :timestamp 946728000 :date_relative \"2000-01-01\" :tags (\"inbox\" \"unread\") :headers (:Subject \"sexp-show-subject\" :From \"Notmuch Test Suite <test_suite@notmuchmail.org>\" :To \"Notmuch Test Suite <test_suite@notmuchmail.org>\" :Bcc \"test_suite+bcc@notmuchmail.org\" :Reply-To \"test_suite+replyto@notmuchmail.org\" :Date \"Sat, 01 Jan 2000 12:00:00 +0000\")) ())))"
-
-test_begin_subtest "Search message: sexp"
-add_message "[subject]=\"sexp-search-subject\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[body]=\"sexp-search-message\""
-output=$(notmuch search --format=sexp "sexp-search-message" | notmuch_search_sanitize)
-test_expect_equal "$output" "((:thread \"0000000000000002\" :timestamp 946728000 :date_relative \"2000-01-01\" :matched 1 :total 1 :authors \"Notmuch Test Suite\" :subject \"sexp-search-subject\" :query (\"id:$gen_msg_id\" nil) :tags (\"inbox\" \"unread\")))"
-
-test_begin_subtest "Show message: sexp, utf-8"
-add_message "[subject]=\"sexp-show-utf8-body-sübjéct\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[body]=\"jsön-show-méssage\""
-output=$(notmuch show --format=sexp "jsön-show-méssage")
-test_expect_equal "$output" "((((:id \"${gen_msg_id}\" :match t :excluded nil :filename \"${gen_msg_filename}\" :timestamp 946728000 :date_relative \"2000-01-01\" :tags (\"inbox\" \"unread\") :headers (:Subject \"sexp-show-utf8-body-sübjéct\" :From \"Notmuch Test Suite <test_suite@notmuchmail.org>\" :To \"Notmuch Test Suite <test_suite@notmuchmail.org>\" :Date \"Sat, 01 Jan 2000 12:00:00 +0000\") :body ((:id 1 :content-type \"text/plain\" :content \"jsön-show-méssage\n\"))) ())))"
-
-test_begin_subtest "Show message: sexp, inline attachment filename"
-subject='sexp-show-inline-attachment-filename'
-id="sexp-show-inline-attachment-filename@notmuchmail.org"
-emacs_fcc_message \
- "$subject" \
- 'This is a test message with inline attachment with a filename' \
- "(mml-attach-file \"$TEST_DIRECTORY/README\" nil nil \"inline\")
- (message-goto-eoh)
- (insert \"Message-ID: <$id>\n\")"
-output=$(notmuch show --format=sexp "id:$id")
-filename=$(notmuch search --output=files "id:$id")
-# Get length of README after base64-encoding, minus additional newline.
-attachment_length=$(( $(base64 $TEST_DIRECTORY/README | wc -c) - 1 ))
-test_expect_equal "$output" "((((:id \"$id\" :match t :excluded nil :filename \"$filename\" :timestamp 946728000 :date_relative \"2000-01-01\" :tags (\"inbox\") :headers (:Subject \"sexp-show-inline-attachment-filename\" :From \"Notmuch Test Suite <test_suite@notmuchmail.org>\" :To \"test_suite@notmuchmail.org\" :Date \"Sat, 01 Jan 2000 12:00:00 +0000\") :body ((:id 1 :content-type \"multipart/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\" :content-transfer-encoding \"base64\" :content-length $attachment_length))))) ())))"
-
-test_begin_subtest "Search message: sexp, utf-8"
-add_message "[subject]=\"sexp-search-utf8-body-sübjéct\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[body]=\"jsön-search-méssage\""
-output=$(notmuch search --format=sexp "jsön-search-méssage" | notmuch_search_sanitize)
-test_expect_equal "$output" "((:thread \"0000000000000005\" :timestamp 946728000 :date_relative \"2000-01-01\" :matched 1 :total 1 :authors \"Notmuch Test Suite\" :subject \"sexp-search-utf8-body-sübjéct\" :query (\"id:$gen_msg_id\" nil) :tags (\"inbox\" \"unread\")))"
-
-
-test_done
+++ /dev/null
-#!/usr/bin/env bash
-#
-# Copyright (c) 2011 David Bremner
-#
-
-# This test tests whether hiding Xapian::Error symbols in libnotmuch
-# also hides them for other users of libxapian. This is motivated by
-# the discussion in http://gcc.gnu.org/wiki/Visibility'
-
-test_description='exception symbol hiding'
-
-. ./test-lib.sh
-
-run_test(){
- result=$(LD_LIBRARY_PATH="$TEST_DIRECTORY/../lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" $TEST_DIRECTORY/symbol-test 2>&1)
-}
-
-output="A Xapian exception occurred opening database: Couldn't stat 'fakedb/.notmuch/xapian'
-caught No chert database found at path \`./nonexistant'"
-
-mkdir -p fakedb/.notmuch
-
-test_expect_success 'running test' run_test
-
-test_begin_subtest 'checking output'
-test_expect_equal "$result" "$output"
-
-test_begin_subtest 'comparing existing to exported symbols'
-objdump -t $TEST_DIRECTORY/../lib/*.o | awk '$4 == ".text" && $6 ~ "^notmuch" {print $6}' | sort | uniq > ACTUAL
-sed -n 's/[[:blank:]]*\(notmuch_[^;]*\);/\1/p' $TEST_DIRECTORY/../notmuch.sym | sort | uniq > EXPORTED
-test_expect_equal_file EXPORTED ACTUAL
-
-test_done
+++ /dev/null
-#!/usr/bin/env bash
-test_description='"notmuch tag"'
-. ./test-lib.sh
-
-add_message '[subject]=One'
-add_message '[subject]=Two'
-
-test_begin_subtest "Adding tags"
-notmuch tag +tag1 +tag2 +tag3 \*
-output=$(notmuch search \* | notmuch_search_sanitize)
-test_expect_equal "$output" "\
-thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; One (inbox tag1 tag2 tag3 unread)
-thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Two (inbox tag1 tag2 tag3 unread)"
-
-test_begin_subtest "Removing tags"
-notmuch tag -tag1 -tag2 \*
-output=$(notmuch search \* | notmuch_search_sanitize)
-test_expect_equal "$output" "\
-thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; One (inbox tag3 unread)
-thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Two (inbox tag3 unread)"
-
-test_expect_code 1 "No tag operations" 'notmuch tag One'
-test_expect_code 1 "No query" 'notmuch tag +tag2'
-
-test_begin_subtest "Redundant tagging"
-notmuch tag +tag1 -tag3 One
-notmuch tag +tag1 -tag3 \*
-output=$(notmuch search \* | notmuch_search_sanitize)
-test_expect_equal "$output" "\
-thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; One (inbox tag1 unread)
-thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Two (inbox tag1 unread)"
-
-test_begin_subtest "Remove all"
-notmuch tag --remove-all One
-notmuch tag --remove-all +tag5 +tag6 +unread Two
-output=$(notmuch search \* | notmuch_search_sanitize)
-test_expect_equal "$output" "\
-thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; One ()
-thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Two (tag5 tag6 unread)"
-
-test_begin_subtest "Remove all with a no-op"
-notmuch tag +inbox +tag1 +unread One
-notmuch tag --remove-all +foo +inbox +tag1 -foo +unread Two
-output=$(notmuch search \* | notmuch_search_sanitize)
-test_expect_equal "$output" "\
-thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; One (inbox tag1 unread)
-thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Two (inbox tag1 unread)"
-
-test_begin_subtest "Special characters in tags"
-notmuch tag +':" ' \*
-notmuch tag -':" ' Two
-output=$(notmuch search \* | notmuch_search_sanitize)
-test_expect_equal "$output" "\
-thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; One (:\" inbox tag1 unread)
-thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Two (inbox tag1 unread)"
-
-test_begin_subtest "Tagging order"
-notmuch tag +tag4 -tag4 One
-notmuch tag -tag4 +tag4 Two
-output=$(notmuch search \* | notmuch_search_sanitize)
-test_expect_equal "$output" "\
-thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; One (:\" inbox tag1 unread)
-thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Two (inbox tag1 tag4 unread)"
-
-test_begin_subtest "--batch"
-notmuch tag --batch <<EOF
-# %20 is a space in tag
--:"%20 -tag1 +tag5 +tag6 -- One
-+tag1 -tag1 -tag4 +tag4 -- Two
--tag6 One
-+tag5 Two
-EOF
-output=$(notmuch search \* | notmuch_search_sanitize)
-test_expect_equal "$output" "\
-thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; One (inbox tag5 unread)
-thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Two (inbox tag4 tag5 unread)"
-
-# generate a common input file for the next several tests.
-cat > batch.in <<EOF
-# %40 is an @ in tag
-+%40 -tag5 +tag6 -- One
-+tag1 -tag1 -tag4 +tag4 -- Two
--tag5 +tag6 Two
-EOF
-
-cat > batch.expected <<EOF
-thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; One (@ inbox tag6 unread)
-thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Two (inbox tag4 tag6 unread)
-EOF
-
-test_begin_subtest "--input"
-notmuch dump --format=batch-tag > backup.tags
-notmuch tag --input=batch.in
-notmuch search \* | notmuch_search_sanitize > OUTPUT
-notmuch restore --format=batch-tag < backup.tags
-test_expect_equal_file batch.expected OUTPUT
-
-test_begin_subtest "--batch --input"
-notmuch dump --format=batch-tag > backup.tags
-notmuch tag --batch --input=batch.in
-notmuch search \* | notmuch_search_sanitize > OUTPUT
-notmuch restore --format=batch-tag < backup.tags
-test_expect_equal_file batch.expected OUTPUT
-
-test_begin_subtest "--batch, blank lines and comments"
-notmuch dump | sort > EXPECTED
-notmuch tag --batch <<EOF
-# this line is a comment; the next has only white space
-
-
-# the previous line is empty
-EOF
-notmuch dump | sort > OUTPUT
-test_expect_equal_file EXPECTED OUTPUT
-
-test_begin_subtest '--batch: checking error messages'
-notmuch dump --format=batch-tag > BACKUP
-notmuch tag --batch <<EOF 2>OUTPUT
-# the next line has a space
-
-# this line has no tag operations, but this is permitted in batch format.
-a
-+0
-+a +b
-# trailing whitespace
-+a +b
-+c +d --
-# this is a harmless comment, do not yell about it.
-
-# the previous line was blank; also no yelling please
-+%zz -- id:whatever
-# the next non-comment line should report an an empty tag error for
-# batch tagging, but not for restore
-+ +e -- id:foo
-+- -- id:foo
-EOF
-
-cat <<EOF > EXPECTED
-Warning: no query string [+0]
-Warning: no query string [+a +b]
-Warning: missing query string [+a +b ]
-Warning: no query string after -- [+c +d --]
-Warning: hex decoding of tag %zz failed [+%zz -- id:whatever]
-Warning: empty tag forbidden [+ +e -- id:foo]
-Warning: tag starting with '-' forbidden [+- -- id:foo]
-EOF
-
-notmuch restore --format=batch-tag < BACKUP
-test_expect_equal_file EXPECTED OUTPUT
-
-test_begin_subtest '--batch: tags with quotes'
-notmuch dump --format=batch-tag > BACKUP
-
-notmuch tag --batch <<EOF
-+%22%27%22%27%22%22%27%27 -- One
--%22%27%22%27%22%22%27%27 -- One
-+%22%27%22%22%22%27 -- One
-+%22%27%22%27%22%22%27%27 -- Two
-EOF
-
-cat <<EOF > EXPECTED
-+%22%27%22%22%22%27 +inbox +tag5 +unread -- id:msg-001@notmuch-test-suite
-+%22%27%22%27%22%22%27%27 +inbox +tag4 +tag5 +unread -- id:msg-002@notmuch-test-suite
-EOF
-
-notmuch dump --format=batch-tag | sort > OUTPUT
-notmuch restore --format=batch-tag < BACKUP
-test_expect_equal_file EXPECTED OUTPUT
-
-test_begin_subtest '--batch: tags with punctuation and space'
-notmuch dump --format=batch-tag > BACKUP
-
-notmuch tag --batch <<EOF
-+%21@%23%24%25%5e%26%2a%29-_=+%5b%7b%5c%20%7c%3b%3a%27%20%22,.%3c%60%7e -- One
--%21@%23%24%25%5e%26%2a%29-_=+%5b%7b%5c%20%7c%3b%3a%27%20%22,.%3c%60%7e -- One
-+%21@%23%24%25%5e%26%2a%29-_=+%5b%7b%5c%20%7c%3b%3a%27%20%22,.%3c%20%60%7e -- Two
--%21@%23%24%25%5e%26%2a%29-_=+%5b%7b%5c%20%7c%3b%3a%27%20%22,.%3c%20%60%7e -- Two
-+%21@%23%20%24%25%5e%26%2a%29-_=+%5b%7b%5c%20%7c%3b%3a%27%20%22,.%3c%60%7e -- One
-+%21@%23%20%24%25%5e%26%2a%29-_=+%5b%7b%5c%20%7c%3b%3a%27%20%22,.%3c%60%7e -- Two
-EOF
-
-cat <<EOF > EXPECTED
-+%21@%23%20%24%25%5e%26%2a%29-_=+%5b%7b%5c%20%7c%3b%3a%27%20%22,.%3c%60%7e +inbox +tag4 +tag5 +unread -- id:msg-002@notmuch-test-suite
-+%21@%23%20%24%25%5e%26%2a%29-_=+%5b%7b%5c%20%7c%3b%3a%27%20%22,.%3c%60%7e +inbox +tag5 +unread -- id:msg-001@notmuch-test-suite
-EOF
-
-notmuch dump --format=batch-tag | sort > OUTPUT
-notmuch restore --format=batch-tag < BACKUP
-test_expect_equal_file EXPECTED OUTPUT
-
-test_begin_subtest '--batch: unicode tags'
-notmuch dump --format=batch-tag > BACKUP
-
-notmuch tag --batch <<EOF
-+%2a@%7d%cf%b5%f4%85%80%adO3%da%a7 -- One
-+=%e0%ac%95%c8%b3+%ef%aa%95%c8%a64w%c7%9d%c9%a2%cf%b3%d6%82%24B%c4%a9%c5%a1UX%ee%99%b0%27E7%ca%a4%d0%8b%5d -- One
-+A%e1%a0%bc%de%8b%d5%b2V%d9%9b%f3%b5%a2%a3M%d8%a1u@%f0%a0%ac%948%7e%f0%ab%86%af%27 -- One
-+R -- One
-+%da%88=f%cc%b9I%ce%af%7b%c9%97%e3%b9%8bH%cb%92X%d2%8c6 -- One
-+%dc%9crh%d2%86B%e5%97%a2%22t%ed%99%82d -- One
-+L%df%85%ef%a1%a5m@%d3%96%c2%ab%d4%9f%ca%b8%f3%b3%a2%bf%c7%b1_u%d7%b4%c7%b1 -- One
-+P%c4%98%2f -- One
-+%7e%d1%8b%25%ec%a0%ae%d1%a0M%3b%e3%b6%b7%e9%a4%87%3c%db%9a%cc%a8%e1%96%9d -- One
-+%c4%bf7%c7%ab9H%c4%99k%ea%91%bd%c3%8ck%e2%b3%8dk%c5%952V%e4%99%b2%d9%b3%e4%8b%bda%5b%24%c7%9b -- One
-+%2a@%7d%cf%b5%f4%85%80%adO3%da%a7 +=%e0%ac%95%c8%b3+%ef%aa%95%c8%a64w%c7%9d%c9%a2%cf%b3%d6%82%24B%c4%a9%c5%a1UX%ee%99%b0%27E7%ca%a4%d0%8b%5d +A%e1%a0%bc%de%8b%d5%b2V%d9%9b%f3%b5%a2%a3M%d8%a1u@%f0%a0%ac%948%7e%f0%ab%86%af%27 +R +%da%88=f%cc%b9I%ce%af%7b%c9%97%e3%b9%8bH%cb%92X%d2%8c6 +%dc%9crh%d2%86B%e5%97%a2%22t%ed%99%82d +L%df%85%ef%a1%a5m@%d3%96%c2%ab%d4%9f%ca%b8%f3%b3%a2%bf%c7%b1_u%d7%b4%c7%b1 +P%c4%98%2f +%7e%d1%8b%25%ec%a0%ae%d1%a0M%3b%e3%b6%b7%e9%a4%87%3c%db%9a%cc%a8%e1%96%9d +%c4%bf7%c7%ab9H%c4%99k%ea%91%bd%c3%8ck%e2%b3%8dk%c5%952V%e4%99%b2%d9%b3%e4%8b%bda%5b%24%c7%9b -- Two
-EOF
-
-cat <<EOF > EXPECTED
-+%2a@%7d%cf%b5%f4%85%80%adO3%da%a7 +=%e0%ac%95%c8%b3+%ef%aa%95%c8%a64w%c7%9d%c9%a2%cf%b3%d6%82%24B%c4%a9%c5%a1UX%ee%99%b0%27E7%ca%a4%d0%8b%5d +A%e1%a0%bc%de%8b%d5%b2V%d9%9b%f3%b5%a2%a3M%d8%a1u@%f0%a0%ac%948%7e%f0%ab%86%af%27 +L%df%85%ef%a1%a5m@%d3%96%c2%ab%d4%9f%ca%b8%f3%b3%a2%bf%c7%b1_u%d7%b4%c7%b1 +P%c4%98%2f +R +inbox +tag4 +tag5 +unread +%7e%d1%8b%25%ec%a0%ae%d1%a0M%3b%e3%b6%b7%e9%a4%87%3c%db%9a%cc%a8%e1%96%9d +%c4%bf7%c7%ab9H%c4%99k%ea%91%bd%c3%8ck%e2%b3%8dk%c5%952V%e4%99%b2%d9%b3%e4%8b%bda%5b%24%c7%9b +%da%88=f%cc%b9I%ce%af%7b%c9%97%e3%b9%8bH%cb%92X%d2%8c6 +%dc%9crh%d2%86B%e5%97%a2%22t%ed%99%82d -- id:msg-002@notmuch-test-suite
-+%2a@%7d%cf%b5%f4%85%80%adO3%da%a7 +=%e0%ac%95%c8%b3+%ef%aa%95%c8%a64w%c7%9d%c9%a2%cf%b3%d6%82%24B%c4%a9%c5%a1UX%ee%99%b0%27E7%ca%a4%d0%8b%5d +A%e1%a0%bc%de%8b%d5%b2V%d9%9b%f3%b5%a2%a3M%d8%a1u@%f0%a0%ac%948%7e%f0%ab%86%af%27 +L%df%85%ef%a1%a5m@%d3%96%c2%ab%d4%9f%ca%b8%f3%b3%a2%bf%c7%b1_u%d7%b4%c7%b1 +P%c4%98%2f +R +inbox +tag5 +unread +%7e%d1%8b%25%ec%a0%ae%d1%a0M%3b%e3%b6%b7%e9%a4%87%3c%db%9a%cc%a8%e1%96%9d +%c4%bf7%c7%ab9H%c4%99k%ea%91%bd%c3%8ck%e2%b3%8dk%c5%952V%e4%99%b2%d9%b3%e4%8b%bda%5b%24%c7%9b +%da%88=f%cc%b9I%ce%af%7b%c9%97%e3%b9%8bH%cb%92X%d2%8c6 +%dc%9crh%d2%86B%e5%97%a2%22t%ed%99%82d -- id:msg-001@notmuch-test-suite
-EOF
-
-notmuch dump --format=batch-tag | sort > OUTPUT
-notmuch restore --format=batch-tag < BACKUP
-test_expect_equal_file EXPECTED OUTPUT
-
-test_begin_subtest "--batch: only space and % needs to be encoded."
-notmuch dump --format=batch-tag > BACKUP
-
-notmuch tag --batch <<EOF
-+winner *
-+foo::bar%25 -- (One and Two) or (One and tag:winner)
-+found::it -- tag:foo::bar%
-# ignore this line and the next
-
-+space%20in%20tags -- Two
-# add tag '(tags)', among other stunts.
-+crazy{ +(tags) +&are +#possible\ -- tag:"space in tags"
-+match*crazy -- tag:crazy{
-+some_tag -- id:"this is ""nauty)"""
-EOF
-
-cat <<EOF > EXPECTED
-+%23possible%5c +%26are +%28tags%29 +crazy%7b +inbox +match%2acrazy +space%20in%20tags +tag4 +tag5 +unread +winner -- id:msg-002@notmuch-test-suite
-+foo%3a%3abar%25 +found%3a%3ait +inbox +tag5 +unread +winner -- id:msg-001@notmuch-test-suite
-EOF
-
-notmuch dump --format=batch-tag | sort > OUTPUT
-notmuch restore --format=batch-tag < BACKUP
-test_expect_equal_file EXPECTED OUTPUT
-
-test_begin_subtest '--batch: unicode message-ids'
-
-${TEST_DIRECTORY}/random-corpus --config-path=${NOTMUCH_CONFIG} \
- --num-messages=100
-
-notmuch dump --format=batch-tag | sed 's/^.* -- /+common_tag -- /' | \
- sort > EXPECTED
-
-notmuch dump --format=batch-tag | sed 's/^.* -- / -- /' | \
- notmuch restore --format=batch-tag
-
-notmuch tag --batch < EXPECTED
-
-notmuch dump --format=batch-tag| \
- sort > OUTPUT
-
-test_expect_equal_file EXPECTED OUTPUT
-
-test_expect_code 1 "Empty tag names" 'notmuch tag + One'
-
-test_expect_code 1 "Tag name beginning with -" 'notmuch tag +- One'
-
-test_done
# Make sure echo builtin does not expand backslash-escape sequences by default.
shopt -u xpg_echo
+this_test=${0##*/}
+this_test=${this_test%.sh}
+this_test_bare=${this_test#T[0-9][0-9][0-9]-}
+
# if --tee was passed, write the output not only to the terminal, but
# additionally to the file test-results/$BASENAME.out, too.
case "$GIT_TEST_TEE_STARTED, $* " in
;;
*' --tee '*|*' --va'*)
mkdir -p test-results
- BASE=test-results/$(basename "$0" .sh)
+ BASE=test-results/$this_test
(GIT_TEST_TEE_STARTED=done ${SHELL-sh} "$0" "$@" 2>&1;
echo $? > $BASE.exit) | tee $BASE.out
test "$(cat $BASE.exit)" = 0
exit 0
fi
-echo $(basename "$0"): "Testing ${test_description}"
+test_description_printed=
+print_test_description ()
+{
+ test -z "$test_description_printed" || return 0
+ echo
+ echo $this_test_bare: "Testing ${test_description}"
+ test_description_printed=1
+}
+if [ -z "$NOTMUCH_TEST_QUIET" ]
+then
+ print_test_description
+fi
exec 5>&1
return
fi
test_success=$(($test_success + 1))
+ if test -n "$NOTMUCH_TEST_QUIET"; then
+ return 0
+ fi
say_color pass "%-6s" "PASS"
echo " $test_subtest_name"
}
return
fi
test_failure=$(($test_failure + 1))
+ print_test_description
test_failure_message_ "FAIL" "$test_subtest_name" "$@"
test "$immediate" = "" || { GIT_EXIT_OK=t; exit 1; }
return 1
GIT_EXIT_OK=t
test_results_dir="$TEST_DIRECTORY/test-results"
mkdir -p "$test_results_dir"
- test_results_path="$test_results_dir/${0%.sh}"
+ test_results_path="$test_results_dir/$this_test"
echo "total $test_count" >> $test_results_path
echo "success $test_success" >> $test_results_path
echo "failed $test_failure" >> $test_results_path
echo "" >> $test_results_path
- echo
-
[ -n "$EMACS_SERVER" ] && test_emacs '(kill-emacs)'
if [ "$test_failure" = "0" ]; then
test -z "$missing_dependencies" || return
if [ -z "$EMACS_SERVER" ]; then
- emacs_tests="$(basename $0).el"
+ emacs_tests="${this_test_bare}.el"
if [ -f "$TEST_DIRECTORY/$emacs_tests" ]; then
load_emacs_tests="--eval '(load \"$emacs_tests\")'"
else
exec 4>test.output 3>&4
fi
-this_test=${0##*/}
for skp in $NOTMUCH_SKIP_TESTS
do
to_skip=
+
test-verbose: Testing the verbosity options of the test framework itself.
PASS print something in test_expect_success and pass
FAIL print something in test_expect_success and fail
+
test-verbose: Testing the verbosity options of the test framework itself.
hello stdout
hello stderr
+++ /dev/null
-#!/usr/bin/env bash
-test_description="--format=text output"
-. ./test-lib.sh
-
-test_begin_subtest "Show message: text"
-add_message "[subject]=\"text-show-subject\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[body]=\"text-show-message\""
-output=$(notmuch show --format=text "text-show-message" | notmuch_show_sanitize_all)
-test_expect_equal "$output" "\
-\fmessage{ id:XXXXX depth:0 match:1 excluded:0 filename:XXXXX
-\fheader{
-Notmuch Test Suite <test_suite@notmuchmail.org> (2000-01-01) (inbox unread)
-Subject: text-show-subject
-From: Notmuch Test Suite <test_suite@notmuchmail.org>
-To: Notmuch Test Suite <test_suite@notmuchmail.org>
-Date: Sat, 01 Jan 2000 12:00:00 +0000
-\fheader}
-\fbody{
-\fpart{ ID: 1, Content-type: text/plain
-text-show-message
-\fpart}
-\fbody}
-\fmessage}"
-
-test_begin_subtest "Search message: text"
-add_message "[subject]=\"text-search-subject\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[body]=\"text-search-message\""
-output=$(notmuch search --format=text "text-search-message" | notmuch_search_sanitize)
-test_expect_equal "$output" \
-"thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; text-search-subject (inbox unread)"
-
-test_begin_subtest "Show message: text, utf-8"
-add_message "[subject]=\"text-show-utf8-body-sübjéct\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[body]=\"tëxt-show-méssage\""
-output=$(notmuch show --format=text "tëxt-show-méssage" | notmuch_show_sanitize_all)
-test_expect_equal "$output" "\
-\fmessage{ id:XXXXX depth:0 match:1 excluded:0 filename:XXXXX
-\fheader{
-Notmuch Test Suite <test_suite@notmuchmail.org> (2000-01-01) (inbox unread)
-Subject: text-show-utf8-body-sübjéct
-From: Notmuch Test Suite <test_suite@notmuchmail.org>
-To: Notmuch Test Suite <test_suite@notmuchmail.org>
-Date: Sat, 01 Jan 2000 12:00:00 +0000
-\fheader}
-\fbody{
-\fpart{ ID: 1, Content-type: text/plain
-tëxt-show-méssage
-\fpart}
-\fbody}
-\fmessage}"
-
-test_begin_subtest "Search message: text, utf-8"
-add_message "[subject]=\"text-search-utf8-body-sübjéct\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[body]=\"tëxt-search-méssage\""
-output=$(notmuch search --format=text "tëxt-search-méssage" | notmuch_search_sanitize)
-test_expect_equal "$output" \
-"thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; text-search-utf8-body-sübjéct (inbox unread)"
-
-add_email_corpus
-
-test_begin_subtest "Search message tags: text0"
-cat <<EOF > EXPECTED
-attachment inbox signed unread
-EOF
-notmuch search --format=text0 --output=tags '*' | xargs -0 | notmuch_search_sanitize > OUTPUT
-test_expect_equal_file EXPECTED OUTPUT
-
-# Use tr(1) to convert --output=text0 to --output=text for
-# comparison. Also translate newlines to spaces to fail with more
-# noise if they are present as delimiters instead of null
-# characters. This assumes there are no newlines in the data.
-test_begin_subtest "Compare text vs. text0 for threads"
-notmuch search --format=text --output=threads '*' | notmuch_search_sanitize > EXPECTED
-notmuch search --format=text0 --output=threads '*' | tr "\n\0" " \n" | notmuch_search_sanitize > OUTPUT
-test_expect_equal_file EXPECTED OUTPUT
-
-test_begin_subtest "Compare text vs. text0 for messages"
-notmuch search --format=text --output=messages '*' | notmuch_search_sanitize > EXPECTED
-notmuch search --format=text0 --output=messages '*' | tr "\n\0" " \n" | notmuch_search_sanitize > OUTPUT
-test_expect_equal_file EXPECTED OUTPUT
-
-test_begin_subtest "Compare text vs. text0 for files"
-notmuch search --format=text --output=files '*' | notmuch_search_sanitize > EXPECTED
-notmuch search --format=text0 --output=files '*' | tr "\n\0" " \n" | notmuch_search_sanitize > OUTPUT
-test_expect_equal_file EXPECTED OUTPUT
-
-test_begin_subtest "Compare text vs. text0 for tags"
-notmuch search --format=text --output=tags '*' | notmuch_search_sanitize > EXPECTED
-notmuch search --format=text0 --output=tags '*' | tr "\n\0" " \n" | notmuch_search_sanitize > OUTPUT
-test_expect_equal_file EXPECTED OUTPUT
-
-test_done
+++ /dev/null
-#!/usr/bin/env bash
-test_description="naming of threads with changing subject"
-. ./test-lib.sh
-
-test_begin_subtest "Initial thread name (oldest-first search)"
-add_message '[subject]="thread-naming: Initial thread subject"' \
- '[date]="Fri, 05 Jan 2001 15:43:56 -0000"'
-first=${gen_msg_cnt}
-parent=${gen_msg_id}
-add_message '[subject]="thread-naming: Older changed subject"' \
- '[date]="Sat, 06 Jan 2001 15:43:56 -0000"' \
- "[in-reply-to]=\<$parent\>"
-add_message '[subject]="thread-naming: Newer changed subject"' \
- '[date]="Sun, 07 Jan 2001 15:43:56 -0000"' \
- "[in-reply-to]=\<$parent\>"
-add_message '[subject]="thread-naming: Final thread subject"' \
- '[date]="Mon, 08 Jan 2001 15:43:56 -0000"' \
- "[in-reply-to]=\<$parent\>"
-final=${gen_msg_id}
-output=$(notmuch search --sort=oldest-first thread-naming and tag:inbox | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2001-01-05 [4/4] Notmuch Test Suite; thread-naming: Initial thread subject (inbox unread)"
-
-test_begin_subtest "Initial thread name (newest-first search)"
-output=$(notmuch search --sort=newest-first thread-naming and tag:inbox | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2001-01-08 [4/4] Notmuch Test Suite; thread-naming: Final thread subject (inbox unread)"
-
-# Remove oldest and newest messages from search results
-notmuch tag -inbox id:$parent or id:$final
-
-test_begin_subtest "Changed thread name (oldest-first search)"
-output=$(notmuch search --sort=oldest-first thread-naming and tag:inbox | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2001-01-06 [2/4] Notmuch Test Suite; thread-naming: Older changed subject (inbox unread)"
-
-test_begin_subtest "Changed thread name (newest-first search)"
-output=$(notmuch search --sort=newest-first thread-naming and tag:inbox | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2001-01-07 [2/4] Notmuch Test Suite; thread-naming: Newer changed subject (inbox unread)"
-
-test_begin_subtest "Ignore added reply prefix (Re:)"
-add_message '[subject]="Re: thread-naming: Initial thread subject"' \
- '[date]="Tue, 09 Jan 2001 15:43:45 -0000"' \
- "[in-reply-to]=\<$parent\>"
-output=$(notmuch search --sort=newest-first thread-naming and tag:inbox | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2001-01-09 [3/5] Notmuch Test Suite; thread-naming: Initial thread subject (inbox unread)"
-
-test_begin_subtest "Ignore added reply prefix (Aw:)"
-add_message '[subject]="Aw: thread-naming: Initial thread subject"' \
- '[date]="Wed, 10 Jan 2001 15:43:45 -0000"' \
- "[in-reply-to]=\<$parent\>"
-output=$(notmuch search --sort=newest-first thread-naming and tag:inbox | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2001-01-10 [4/6] Notmuch Test Suite; thread-naming: Initial thread subject (inbox unread)"
-
-test_begin_subtest "Ignore added reply prefix (Vs:)"
-add_message '[subject]="Vs: thread-naming: Initial thread subject"' \
- '[date]="Thu, 11 Jan 2001 15:43:45 -0000"' \
- "[in-reply-to]=\<$parent\>"
-output=$(notmuch search --sort=newest-first thread-naming and tag:inbox | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2001-01-11 [5/7] Notmuch Test Suite; thread-naming: Initial thread subject (inbox unread)"
-
-test_begin_subtest "Ignore added reply prefix (Sv:)"
-add_message '[subject]="Sv: thread-naming: Initial thread subject"' \
- '[date]="Fri, 12 Jan 2001 15:43:45 -0000"' \
- "[in-reply-to]=\<$parent\>"
-output=$(notmuch search --sort=newest-first thread-naming and tag:inbox | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2001-01-12 [6/8] Notmuch Test Suite; thread-naming: Initial thread subject (inbox unread)"
-
-test_begin_subtest 'Test order of messages in "notmuch show"'
-output=$(notmuch show thread-naming | notmuch_show_sanitize)
-test_expect_equal "$output" "\fmessage{ id:msg-$(printf "%03d" $first)@notmuch-test-suite depth:0 match:1 excluded:0 filename:/XXX/mail/msg-$(printf "%03d" $first)
-\fheader{
-Notmuch Test Suite <test_suite@notmuchmail.org> (2001-01-05) (unread)
-Subject: thread-naming: Initial thread subject
-From: Notmuch Test Suite <test_suite@notmuchmail.org>
-To: Notmuch Test Suite <test_suite@notmuchmail.org>
-Date: Fri, 05 Jan 2001 15:43:56 +0000
-\fheader}
-\fbody{
-\fpart{ ID: 1, Content-type: text/plain
-This is just a test message (#$first)
-\fpart}
-\fbody}
-\fmessage}
-\fmessage{ id:msg-$(printf "%03d" $((first + 1)))@notmuch-test-suite depth:1 match:1 excluded:0 filename:/XXX/mail/msg-$(printf "%03d" $((first + 1)))
-\fheader{
-Notmuch Test Suite <test_suite@notmuchmail.org> (2001-01-06) (inbox unread)
-Subject: thread-naming: Older changed subject
-From: Notmuch Test Suite <test_suite@notmuchmail.org>
-To: Notmuch Test Suite <test_suite@notmuchmail.org>
-Date: Sat, 06 Jan 2001 15:43:56 +0000
-\fheader}
-\fbody{
-\fpart{ ID: 1, Content-type: text/plain
-This is just a test message (#$((first + 1)))
-\fpart}
-\fbody}
-\fmessage}
-\fmessage{ id:msg-$(printf "%03d" $((first + 2)))@notmuch-test-suite depth:1 match:1 excluded:0 filename:/XXX/mail/msg-$(printf "%03d" $((first + 2)))
-\fheader{
-Notmuch Test Suite <test_suite@notmuchmail.org> (2001-01-07) (inbox unread)
-Subject: thread-naming: Newer changed subject
-From: Notmuch Test Suite <test_suite@notmuchmail.org>
-To: Notmuch Test Suite <test_suite@notmuchmail.org>
-Date: Sun, 07 Jan 2001 15:43:56 +0000
-\fheader}
-\fbody{
-\fpart{ ID: 1, Content-type: text/plain
-This is just a test message (#$((first + 2)))
-\fpart}
-\fbody}
-\fmessage}
-\fmessage{ id:msg-$(printf "%03d" $((first + 3)))@notmuch-test-suite depth:1 match:1 excluded:0 filename:/XXX/mail/msg-$(printf "%03d" $((first + 3)))
-\fheader{
-Notmuch Test Suite <test_suite@notmuchmail.org> (2001-01-08) (unread)
-Subject: thread-naming: Final thread subject
-From: Notmuch Test Suite <test_suite@notmuchmail.org>
-To: Notmuch Test Suite <test_suite@notmuchmail.org>
-Date: Mon, 08 Jan 2001 15:43:56 +0000
-\fheader}
-\fbody{
-\fpart{ ID: 1, Content-type: text/plain
-This is just a test message (#$((first + 3)))
-\fpart}
-\fbody}
-\fmessage}
-\fmessage{ id:msg-$(printf "%03d" $((first + 4)))@notmuch-test-suite depth:1 match:1 excluded:0 filename:/XXX/mail/msg-$(printf "%03d" $((first + 4)))
-\fheader{
-Notmuch Test Suite <test_suite@notmuchmail.org> (2001-01-09) (inbox unread)
-Subject: Re: thread-naming: Initial thread subject
-From: Notmuch Test Suite <test_suite@notmuchmail.org>
-To: Notmuch Test Suite <test_suite@notmuchmail.org>
-Date: Tue, 09 Jan 2001 15:43:45 +0000
-\fheader}
-\fbody{
-\fpart{ ID: 1, Content-type: text/plain
-This is just a test message (#$((first + 4)))
-\fpart}
-\fbody}
-\fmessage}
-\fmessage{ id:msg-$(printf "%03d" $((first + 5)))@notmuch-test-suite depth:1 match:1 excluded:0 filename:/XXX/mail/msg-$(printf "%03d" $((first + 5)))
-\fheader{
-Notmuch Test Suite <test_suite@notmuchmail.org> (2001-01-10) (inbox unread)
-Subject: Aw: thread-naming: Initial thread subject
-From: Notmuch Test Suite <test_suite@notmuchmail.org>
-To: Notmuch Test Suite <test_suite@notmuchmail.org>
-Date: Wed, 10 Jan 2001 15:43:45 +0000
-\fheader}
-\fbody{
-\fpart{ ID: 1, Content-type: text/plain
-This is just a test message (#$((first + 5)))
-\fpart}
-\fbody}
-\fmessage}
-\fmessage{ id:msg-$(printf "%03d" $((first + 6)))@notmuch-test-suite depth:1 match:1 excluded:0 filename:/XXX/mail/msg-$(printf "%03d" $((first + 6)))
-\fheader{
-Notmuch Test Suite <test_suite@notmuchmail.org> (2001-01-11) (inbox unread)
-Subject: Vs: thread-naming: Initial thread subject
-From: Notmuch Test Suite <test_suite@notmuchmail.org>
-To: Notmuch Test Suite <test_suite@notmuchmail.org>
-Date: Thu, 11 Jan 2001 15:43:45 +0000
-\fheader}
-\fbody{
-\fpart{ ID: 1, Content-type: text/plain
-This is just a test message (#$((first + 6)))
-\fpart}
-\fbody}
-\fmessage}
-\fmessage{ id:msg-$(printf "%03d" $((first + 7)))@notmuch-test-suite depth:1 match:1 excluded:0 filename:/XXX/mail/msg-$(printf "%03d" $((first + 7)))
-\fheader{
-Notmuch Test Suite <test_suite@notmuchmail.org> (2001-01-12) (inbox unread)
-Subject: Sv: thread-naming: Initial thread subject
-From: Notmuch Test Suite <test_suite@notmuchmail.org>
-To: Notmuch Test Suite <test_suite@notmuchmail.org>
-Date: Fri, 12 Jan 2001 15:43:45 +0000
-\fheader}
-\fbody{
-\fpart{ ID: 1, Content-type: text/plain
-This is just a test message (#$((first + 7)))
-\fpart}
-\fbody}
-\fmessage}"
-test_done
+++ /dev/null
-#!/usr/bin/env bash
-test_description="threading when messages received out of order"
-. ./test-lib.sh
-
-test_begin_subtest "Adding initial child message"
-generate_message [body]=foo "[in-reply-to]=\<parent-id\>" [subject]=brokenthreadtest '[date]="Sat, 01 Jan 2000 12:00:00 -0000"'
-output=$(NOTMUCH_NEW)
-test_expect_equal "$output" "Added 1 new message to the database."
-
-test_begin_subtest "Searching returns the message"
-output=$(notmuch search foo | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; brokenthreadtest (inbox unread)"
-
-test_begin_subtest "Adding second child message"
-generate_message [body]=foo "[in-reply-to]=\<parent-id\>" [subject]=brokenthreadtest '[date]="Sat, 01 Jan 2000 12:00:00 -0000"'
-output=$(NOTMUCH_NEW)
-test_expect_equal "$output" "Added 1 new message to the database."
-
-test_begin_subtest "Searching returns both messages in one thread"
-output=$(notmuch search foo | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2000-01-01 [2/2] Notmuch Test Suite; brokenthreadtest (inbox unread)"
-
-test_begin_subtest "Adding parent message"
-generate_message [body]=foo [id]=parent-id [subject]=brokenthreadtest '[date]="Sat, 01 Jan 2000 12:00:00 -0000"'
-output=$(NOTMUCH_NEW)
-test_expect_equal "$output" "Added 1 new message to the database."
-
-test_begin_subtest "Searching returns all three messages in one thread"
-output=$(notmuch search foo | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2000-01-01 [3/3] Notmuch Test Suite; brokenthreadtest (inbox unread)"
-
-test_done
+++ /dev/null
-#!/usr/bin/env bash
-#
-# Copyright (c) 2013 Aaron Ecay
-#
-
-test_description='test of proper handling of in-reply-to and references headers'
-
-# This test makes sure that the thread structure in the notmuch
-# database is constructed properly, even in the presence of
-# non-RFC-compliant headers'
-
-. ./test-lib.sh
-
-test_begin_subtest "Use References when In-Reply-To is broken"
-add_message '[id]="foo@one.com"' \
- '[subject]=one'
-add_message '[in-reply-to]="mumble"' \
- '[references]="<foo@one.com>"' \
- '[subject]="Re: one"'
-output=$(notmuch show --format=json 'subject:one' | notmuch_json_show_sanitize)
-expected='[[[{"id": "foo@one.com",
- "match": true,
- "excluded": false,
- "filename": "YYYYY",
- "timestamp": 978709437,
- "date_relative": "2001-01-05",
- "tags": ["inbox", "unread"],
- "headers": {"Subject": "one",
- "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
- "To": "Notmuch Test Suite <test_suite@notmuchmail.org>",
- "Date": "Fri, 05 Jan 2001 15:43:57 +0000"},
- "body": [{"id": 1,
- "content-type": "text/plain",
- "content": "This is just a test message (#1)\n"}]},
- [[{"id": "msg-002@notmuch-test-suite",
- "match": true, "excluded": false,
- "filename": "YYYYY",
- "timestamp": 978709437, "date_relative": "2001-01-05",
- "tags": ["inbox", "unread"], "headers": {"Subject": "Re: one",
- "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
- "To": "Notmuch Test Suite <test_suite@notmuchmail.org>",
- "Date": "Fri, 05 Jan 2001 15:43:57 +0000"},
- "body": [{"id": 1, "content-type": "text/plain",
- "content": "This is just a test message (#2)\n"}]}, []]]]]]'
-expected=`echo "$expected" | notmuch_json_show_sanitize`
-test_expect_equal_json "$output" "$expected"
-
-test_begin_subtest "Prefer References to In-Reply-To"
-add_message '[id]="foo@two.com"' \
- '[subject]=two'
-add_message '[in-reply-to]="<bar@baz.com>"' \
- '[references]="<foo@two.com>"' \
- '[subject]="Re: two"'
-output=$(notmuch show --format=json 'subject:two' | notmuch_json_show_sanitize)
-expected='[[[{"id": "foo@two.com",
- "match": true, "excluded": false,
- "filename": "YYYYY",
- "timestamp": 978709437, "date_relative": "2001-01-05", "tags": ["inbox", "unread"],
- "headers": {"Subject": "two",
- "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
- "To": "Notmuch Test Suite <test_suite@notmuchmail.org>",
- "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"}]},
- [[{"id": "msg-004@notmuch-test-suite", "match": true, "excluded": false,
- "filename": "YYYYY",
- "timestamp": 978709437, "date_relative": "2001-01-05", "tags": ["inbox", "unread"],
- "headers": {"Subject": "Re: two",
- "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
- "To": "Notmuch Test Suite <test_suite@notmuchmail.org>",
- "Date": "Fri, 05 Jan 2001 15:43:57 +0000"},
- "body": [{"id": 1,
- "content-type": "text/plain", "content": "This is just a test message (#4)\n"}]},
- []]]]]]'
-expected=`echo "$expected" | notmuch_json_show_sanitize`
-test_expect_equal_json "$output" "$expected"
-
-test_begin_subtest "Use In-Reply-To when no References"
-add_message '[id]="foo@three.com"' \
- '[subject]="three"'
-add_message '[in-reply-to]="<foo@three.com>"' \
- '[subject]="Re: three"'
-output=$(notmuch show --format=json 'subject:three' | notmuch_json_show_sanitize)
-expected='[[[{"id": "foo@three.com", "match": true, "excluded": false,
- "filename": "YYYYY",
- "timestamp": 978709437, "date_relative": "2001-01-05", "tags": ["inbox", "unread"],
- "headers": {"Subject": "three",
- "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
- "To": "Notmuch Test Suite <test_suite@notmuchmail.org>",
- "Date": "Fri, 05 Jan 2001 15:43:57 +0000"}, "body": [{"id": 1,
- "content-type": "text/plain", "content": "This is just a test message (#5)\n"}]},
- [[{"id": "msg-006@notmuch-test-suite", "match": true, "excluded": false,
- "filename": "YYYYY",
- "timestamp": 978709437, "date_relative": "2001-01-05", "tags": ["inbox", "unread"],
- "headers": {"Subject": "Re: three",
- "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
- "To": "Notmuch Test Suite <test_suite@notmuchmail.org>",
- "Date": "Fri, 05 Jan 2001 15:43:57 +0000"}, "body": [{"id": 1,
- "content-type": "text/plain", "content": "This is just a test message (#6)\n"}]},
- []]]]]]'
-expected=`echo "$expected" | notmuch_json_show_sanitize`
-test_expect_equal_json "$output" "$expected"
-
-test_begin_subtest "Use last Reference"
-add_message '[id]="foo@four.com"' \
- '[subject]="four"'
-add_message '[id]="bar@four.com"' \
- '[subject]="not-four"'
-add_message '[in-reply-to]="<baz@four.com>"' \
- '[references]="<baz@four.com> <foo@four.com>"' \
- '[subject]="neither"'
-output=$(notmuch show --format=json 'subject:four' | notmuch_json_show_sanitize)
-expected='[[[{"id": "foo@four.com", "match": true, "excluded": false,
- "filename": "YYYYY",
- "timestamp": 978709437, "date_relative": "2001-01-05", "tags": ["inbox", "unread"],
- "headers": {"Subject": "four",
- "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
- "To": "Notmuch Test Suite <test_suite@notmuchmail.org>",
- "Date": "Fri, 05 Jan 2001 15:43:57 +0000"}, "body": [{"id": 1,
- "content-type": "text/plain", "content": "This is just a test message (#7)\n"}]},
- [[{"id": "msg-009@notmuch-test-suite", "match": false, "excluded": false,
- "filename": "YYYYY",
- "timestamp": 978709437, "date_relative": "2001-01-05", "tags": ["inbox", "unread"],
- "headers": {"Subject": "neither",
- "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
- "To": "Notmuch Test Suite <test_suite@notmuchmail.org>",
- "Date": "Fri, 05 Jan 2001 15:43:57 +0000"}, "body": [{"id": 1,
- "content-type": "text/plain", "content": "This is just a test message (#9)\n"}]},
- []]]]], [[{"id": "bar@four.com", "match": true, "excluded": false,
- "filename": "YYYYY",
- "timestamp": 978709437, "date_relative": "2001-01-05", "tags": ["inbox", "unread"],
- "headers": {"Subject": "not-four",
- "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
- "To": "Notmuch Test Suite <test_suite@notmuchmail.org>",
- "Date": "Fri, 05 Jan 2001 15:43:57 +0000"}, "body": [{"id": 1,
- "content-type": "text/plain", "content": "This is just a test message (#8)\n"}]}, []]]]'
-expected=`echo "$expected" | notmuch_json_show_sanitize`
-test_expect_equal_json "$output" "$expected"
-
-
-test_done
2009-11-17 Mikhail Gusarov ┬►[notmuch] [PATCH 1/2] Close message file after parsing message headers (inbox)
- 2009-11-17 Mikhail Gusarov ├─►[notmuch] [PATCH 2/2] Include <stdint.h> to get uint32_t in C++ file with gcc 4.4 (inbox, unread)
- 2009-11-17 Carl Worth ╰┬►[notmuch] [PATCH 1/2] Close message file after parsing message headers (inbox, unread)
- 2009-11-17 Keith Packard ╰┬► ... (inbox, unread)
- 2009-11-18 Carl Worth ╰─► ... (inbox, unread)
+ 2009-11-17 Mikhail Gusarov ├─►[notmuch] [PATCH 2/2] Include <stdint.h> to get uint32_t in C++ file with gcc 4.4 (inbox unread)
+ 2009-11-17 Carl Worth ╰┬►[notmuch] [PATCH 1/2] Close message file after parsing message headers (inbox unread)
+ 2009-11-17 Keith Packard ╰┬► ... (inbox unread)
+ 2009-11-18 Carl Worth ╰─► ... (inbox unread)
End of search results.
- 2010-12-29 François Boulogne ─►[aur-general] Guidelines: cp, mkdir vs install (inbox, unread)
- 2010-12-16 Olivier Berger ─►Essai accentué (inbox, unread)
- 2009-11-18 Chris Wilson ─►[notmuch] [PATCH 1/2] Makefile: evaluate pkg-config once (inbox, unread)
- 2009-11-18 Alex Botero-Lowry ┬►[notmuch] [PATCH] Error out if no query is supplied to search instead of going into an infinite loop (attachment, inbox, unread)
- 2009-11-18 Carl Worth ╰─►[notmuch] [PATCH] Error out if no query is supplied to search instead of going into an infinite loop (inbox, unread)
- 2009-11-17 Ingmar Vanhassel ┬►[notmuch] [PATCH] Typsos (inbox, unread)
- 2009-11-18 Carl Worth ╰─► ... (inbox, unread)
- 2009-11-17 Adrian Perez de Cast ┬►[notmuch] Introducing myself (inbox, signed, unread)
- 2009-11-18 Keith Packard ├─► ... (inbox, unread)
- 2009-11-18 Carl Worth ╰─► ... (inbox, unread)
- 2009-11-17 Israel Herraiz ┬►[notmuch] New to the list (inbox, unread)
- 2009-11-18 Keith Packard ├─► ... (inbox, unread)
- 2009-11-18 Carl Worth ╰─► ... (inbox, unread)
- 2009-11-17 Jan Janak ┬►[notmuch] What a great idea! (inbox, unread)
- 2009-11-17 Jan Janak ├─► ... (inbox, unread)
- 2009-11-18 Carl Worth ╰─► ... (inbox, unread)
- 2009-11-17 Jan Janak ┬►[notmuch] [PATCH] Older versions of install do not support -C. (inbox, unread)
- 2009-11-18 Carl Worth ╰─► ... (inbox, unread)
- 2009-11-17 Aron Griffis ┬►[notmuch] archive (inbox, unread)
- 2009-11-18 Keith Packard ╰┬► ... (inbox, unread)
- 2009-11-18 Carl Worth ╰─► ... (inbox, unread)
- 2009-11-17 Keith Packard ┬►[notmuch] [PATCH] Make notmuch-show 'X' (and 'x') commands remove inbox (and unread) tags (inbox, unread)
- 2009-11-18 Carl Worth ╰─►[notmuch] [PATCH] Make notmuch-show 'X' (and 'x') commands remove inbox (and unread) tags (inbox, unread)
- 2009-11-17 Lars Kellogg-Stedman ┬►[notmuch] Working with Maildir storage? (inbox, signed, unread)
- 2009-11-17 Mikhail Gusarov ├┬► ... (inbox, signed, unread)
- 2009-11-17 Lars Kellogg-Stedman │╰┬► ... (inbox, signed, unread)
- 2009-11-17 Mikhail Gusarov │ ├─► ... (inbox, unread)
- 2009-11-17 Keith Packard │ ╰┬► ... (inbox, unread)
- 2009-11-18 Lars Kellogg-Stedman │ ╰─► ... (inbox, signed, unread)
- 2009-11-18 Carl Worth ╰─► ... (inbox, unread)
- 2009-11-17 Mikhail Gusarov ┬►[notmuch] [PATCH 1/2] Close message file after parsing message headers (inbox, unread)
- 2009-11-17 Mikhail Gusarov ├─►[notmuch] [PATCH 2/2] Include <stdint.h> to get uint32_t in C++ file with gcc 4.4 (inbox, unread)
- 2009-11-17 Carl Worth ╰┬►[notmuch] [PATCH 1/2] Close message file after parsing message headers (inbox, unread)
- 2009-11-17 Keith Packard ╰┬► ... (inbox, unread)
- 2009-11-18 Carl Worth ╰─► ... (inbox, unread)
- 2009-11-18 Keith Packard ┬►[notmuch] [PATCH] Create a default notmuch-show-hook that highlights URLs and uses word-wrap (inbox, unread)
- 2009-11-18 Alexander Botero-Low ╰─►[notmuch] [PATCH] Create a default notmuch-show-hook that highlights URLs and uses word-wrap (inbox, unread)
- 2009-11-18 Alexander Botero-Low ─►[notmuch] request for pull (inbox, unread)
- 2009-11-18 Jjgod Jiang ┬►[notmuch] Mac OS X/Darwin compatibility issues (inbox, unread)
- 2009-11-18 Alexander Botero-Low ╰┬► ... (inbox, unread)
- 2009-11-18 Jjgod Jiang ╰┬► ... (inbox, unread)
- 2009-11-18 Alexander Botero-Low ╰─► ... (inbox, unread)
- 2009-11-18 Rolland Santimano ─►[notmuch] Link to mailing list archives ? (inbox, unread)
- 2009-11-18 Jan Janak ─►[notmuch] [PATCH] notmuch new: Support for conversion of spool subdirectories into tags (inbox, unread)
- 2009-11-18 Stewart Smith ─►[notmuch] [PATCH] count_files: sort directory in inode order before statting (inbox, unread)
- 2009-11-18 Stewart Smith ─►[notmuch] [PATCH 2/2] Read mail directory in inode number order (inbox, unread)
- 2009-11-18 Stewart Smith ─►[notmuch] [PATCH] Fix linking with gcc to use g++ to link in C++ libs. (inbox, unread)
- 2009-11-18 Lars Kellogg-Stedman ┬►[notmuch] "notmuch help" outputs to stderr? (attachment, inbox, signed, unread)
- 2009-11-18 Lars Kellogg-Stedman ╰─► ... (attachment, inbox, signed, unread)
- 2009-11-17 Mikhail Gusarov ─►[notmuch] [PATCH] Handle rename of message file (inbox, unread)
- 2009-11-17 Alex Botero-Lowry ┬►[notmuch] preliminary FreeBSD support (attachment, inbox, unread)
- 2009-11-17 Carl Worth ╰─► ... (inbox, unread)
+ 2010-12-29 François Boulogne ─►[aur-general] Guidelines: cp, mkdir vs install (inbox unread)
+ 2010-12-16 Olivier Berger ─►Essai accentué (inbox unread)
+ 2009-11-18 Chris Wilson ─►[notmuch] [PATCH 1/2] Makefile: evaluate pkg-config once (inbox unread)
+ 2009-11-18 Alex Botero-Lowry ┬►[notmuch] [PATCH] Error out if no query is supplied to search instead of going into an infinite loop (attachment inbox unread)
+ 2009-11-18 Carl Worth ╰─►[notmuch] [PATCH] Error out if no query is supplied to search instead of going into an infinite loop (inbox unread)
+ 2009-11-17 Ingmar Vanhassel ┬►[notmuch] [PATCH] Typsos (inbox unread)
+ 2009-11-18 Carl Worth ╰─► ... (inbox unread)
+ 2009-11-17 Adrian Perez de Cast ┬►[notmuch] Introducing myself (inbox signed unread)
+ 2009-11-18 Keith Packard ├─► ... (inbox unread)
+ 2009-11-18 Carl Worth ╰─► ... (inbox unread)
+ 2009-11-17 Israel Herraiz ┬►[notmuch] New to the list (inbox unread)
+ 2009-11-18 Keith Packard ├─► ... (inbox unread)
+ 2009-11-18 Carl Worth ╰─► ... (inbox unread)
+ 2009-11-17 Jan Janak ┬►[notmuch] What a great idea! (inbox unread)
+ 2009-11-17 Jan Janak ├─► ... (inbox unread)
+ 2009-11-18 Carl Worth ╰─► ... (inbox unread)
+ 2009-11-17 Jan Janak ┬►[notmuch] [PATCH] Older versions of install do not support -C. (inbox unread)
+ 2009-11-18 Carl Worth ╰─► ... (inbox unread)
+ 2009-11-17 Aron Griffis ┬►[notmuch] archive (inbox unread)
+ 2009-11-18 Keith Packard ╰┬► ... (inbox unread)
+ 2009-11-18 Carl Worth ╰─► ... (inbox unread)
+ 2009-11-17 Keith Packard ┬►[notmuch] [PATCH] Make notmuch-show 'X' (and 'x') commands remove inbox (and unread) tags (inbox unread)
+ 2009-11-18 Carl Worth ╰─►[notmuch] [PATCH] Make notmuch-show 'X' (and 'x') commands remove inbox (and unread) tags (inbox unread)
+ 2009-11-17 Lars Kellogg-Stedman ┬►[notmuch] Working with Maildir storage? (inbox signed unread)
+ 2009-11-17 Mikhail Gusarov ├┬► ... (inbox signed unread)
+ 2009-11-17 Lars Kellogg-Stedman │╰┬► ... (inbox signed unread)
+ 2009-11-17 Mikhail Gusarov │ ├─► ... (inbox unread)
+ 2009-11-17 Keith Packard │ ╰┬► ... (inbox unread)
+ 2009-11-18 Lars Kellogg-Stedman │ ╰─► ... (inbox signed unread)
+ 2009-11-18 Carl Worth ╰─► ... (inbox unread)
+ 2009-11-17 Mikhail Gusarov ┬►[notmuch] [PATCH 1/2] Close message file after parsing message headers (inbox unread)
+ 2009-11-17 Mikhail Gusarov ├─►[notmuch] [PATCH 2/2] Include <stdint.h> to get uint32_t in C++ file with gcc 4.4 (inbox unread)
+ 2009-11-17 Carl Worth ╰┬►[notmuch] [PATCH 1/2] Close message file after parsing message headers (inbox unread)
+ 2009-11-17 Keith Packard ╰┬► ... (inbox unread)
+ 2009-11-18 Carl Worth ╰─► ... (inbox unread)
+ 2009-11-18 Keith Packard ┬►[notmuch] [PATCH] Create a default notmuch-show-hook that highlights URLs and uses word-wrap (inbox unread)
+ 2009-11-18 Alexander Botero-Low ╰─►[notmuch] [PATCH] Create a default notmuch-show-hook that highlights URLs and uses word-wrap (inbox unread)
+ 2009-11-18 Alexander Botero-Low ─►[notmuch] request for pull (inbox unread)
+ 2009-11-18 Jjgod Jiang ┬►[notmuch] Mac OS X/Darwin compatibility issues (inbox unread)
+ 2009-11-18 Alexander Botero-Low ╰┬► ... (inbox unread)
+ 2009-11-18 Jjgod Jiang ╰┬► ... (inbox unread)
+ 2009-11-18 Alexander Botero-Low ╰─► ... (inbox unread)
+ 2009-11-18 Rolland Santimano ─►[notmuch] Link to mailing list archives ? (inbox unread)
+ 2009-11-18 Jan Janak ─►[notmuch] [PATCH] notmuch new: Support for conversion of spool subdirectories into tags (inbox unread)
+ 2009-11-18 Stewart Smith ─►[notmuch] [PATCH] count_files: sort directory in inode order before statting (inbox unread)
+ 2009-11-18 Stewart Smith ─►[notmuch] [PATCH 2/2] Read mail directory in inode number order (inbox unread)
+ 2009-11-18 Stewart Smith ─►[notmuch] [PATCH] Fix linking with gcc to use g++ to link in C++ libs. (inbox unread)
+ 2009-11-18 Lars Kellogg-Stedman ┬►[notmuch] "notmuch help" outputs to stderr? (attachment inbox signed unread)
+ 2009-11-18 Lars Kellogg-Stedman ╰─► ... (attachment inbox signed unread)
+ 2009-11-17 Mikhail Gusarov ─►[notmuch] [PATCH] Handle rename of message file (inbox unread)
+ 2009-11-17 Alex Botero-Lowry ┬►[notmuch] preliminary FreeBSD support (attachment inbox unread)
+ 2009-11-17 Carl Worth ╰─► ... (inbox unread)
End of search results.
- 2010-12-29 François Boulogne ─►[aur-general] Guidelines: cp, mkdir vs install (inbox, unread)
- 2010-12-16 Olivier Berger ─►Essai accentué (inbox, test_tag, unread)
- 2009-11-18 Chris Wilson ─►[notmuch] [PATCH 1/2] Makefile: evaluate pkg-config once (inbox, unread)
- 2009-11-18 Alex Botero-Lowry ┬►[notmuch] [PATCH] Error out if no query is supplied to search instead of going into an infinite loop (attachment, inbox, unread)
- 2009-11-18 Carl Worth ╰─►[notmuch] [PATCH] Error out if no query is supplied to search instead of going into an infinite loop (inbox, unread)
- 2009-11-17 Ingmar Vanhassel ┬►[notmuch] [PATCH] Typsos (inbox, unread)
- 2009-11-18 Carl Worth ╰─► ... (inbox, unread)
- 2009-11-17 Adrian Perez de Cast ┬►[notmuch] Introducing myself (inbox, signed, unread)
- 2009-11-18 Keith Packard ├─► ... (inbox, unread)
- 2009-11-18 Carl Worth ╰─► ... (inbox, unread)
- 2009-11-17 Israel Herraiz ┬►[notmuch] New to the list (inbox, unread)
- 2009-11-18 Keith Packard ├─► ... (inbox, unread)
- 2009-11-18 Carl Worth ╰─► ... (inbox, unread)
- 2009-11-17 Jan Janak ┬►[notmuch] What a great idea! (inbox, unread)
- 2009-11-17 Jan Janak ├─► ... (inbox, unread)
- 2009-11-18 Carl Worth ╰─► ... (inbox, unread)
- 2009-11-17 Jan Janak ┬►[notmuch] [PATCH] Older versions of install do not support -C. (inbox, unread)
- 2009-11-18 Carl Worth ╰─► ... (inbox, unread)
- 2009-11-17 Aron Griffis ┬►[notmuch] archive (inbox, unread)
- 2009-11-18 Keith Packard ╰┬► ... (inbox, unread)
- 2009-11-18 Carl Worth ╰─► ... (inbox, unread)
- 2009-11-17 Keith Packard ┬►[notmuch] [PATCH] Make notmuch-show 'X' (and 'x') commands remove inbox (and unread) tags (inbox, unread)
- 2009-11-18 Carl Worth ╰─►[notmuch] [PATCH] Make notmuch-show 'X' (and 'x') commands remove inbox (and unread) tags (inbox, unread)
- 2009-11-17 Lars Kellogg-Stedman ┬►[notmuch] Working with Maildir storage? (inbox, signed, unread)
- 2009-11-17 Mikhail Gusarov ├┬► ... (inbox, signed, unread)
- 2009-11-17 Lars Kellogg-Stedman │╰┬► ... (inbox, signed, unread)
- 2009-11-17 Mikhail Gusarov │ ├─► ... (inbox, unread)
- 2009-11-17 Keith Packard │ ╰┬► ... (inbox, unread)
- 2009-11-18 Lars Kellogg-Stedman │ ╰─► ... (inbox, signed, unread)
- 2009-11-18 Carl Worth ╰─► ... (inbox, unread)
- 2009-11-17 Mikhail Gusarov ┬►[notmuch] [PATCH 1/2] Close message file after parsing message headers (inbox, unread)
- 2009-11-17 Mikhail Gusarov ├─►[notmuch] [PATCH 2/2] Include <stdint.h> to get uint32_t in C++ file with gcc 4.4 (inbox, unread)
- 2009-11-17 Carl Worth ╰┬►[notmuch] [PATCH 1/2] Close message file after parsing message headers (inbox, unread)
- 2009-11-17 Keith Packard ╰┬► ... (inbox, unread)
- 2009-11-18 Carl Worth ╰─► ... (inbox, unread)
- 2009-11-18 Keith Packard ┬►[notmuch] [PATCH] Create a default notmuch-show-hook that highlights URLs and uses word-wrap (inbox, unread)
- 2009-11-18 Alexander Botero-Low ╰─►[notmuch] [PATCH] Create a default notmuch-show-hook that highlights URLs and uses word-wrap (inbox, unread)
- 2009-11-18 Alexander Botero-Low ─►[notmuch] request for pull (inbox, unread)
- 2009-11-18 Jjgod Jiang ┬►[notmuch] Mac OS X/Darwin compatibility issues (inbox, unread)
- 2009-11-18 Alexander Botero-Low ╰┬► ... (inbox, unread)
- 2009-11-18 Jjgod Jiang ╰┬► ... (inbox, unread)
- 2009-11-18 Alexander Botero-Low ╰─► ... (inbox, unread)
- 2009-11-18 Rolland Santimano ─►[notmuch] Link to mailing list archives ? (inbox, unread)
- 2009-11-18 Jan Janak ─►[notmuch] [PATCH] notmuch new: Support for conversion of spool subdirectories into tags (inbox, unread)
- 2009-11-18 Stewart Smith ─►[notmuch] [PATCH] count_files: sort directory in inode order before statting (inbox, unread)
- 2009-11-18 Stewart Smith ─►[notmuch] [PATCH 2/2] Read mail directory in inode number order (inbox, unread)
- 2009-11-18 Stewart Smith ─►[notmuch] [PATCH] Fix linking with gcc to use g++ to link in C++ libs. (inbox, unread)
- 2009-11-18 Lars Kellogg-Stedman ┬►[notmuch] "notmuch help" outputs to stderr? (attachment, inbox, signed, unread)
- 2009-11-18 Lars Kellogg-Stedman ╰─► ... (attachment, inbox, signed, unread)
- 2009-11-17 Mikhail Gusarov ─►[notmuch] [PATCH] Handle rename of message file (inbox, unread)
- 2009-11-17 Alex Botero-Lowry ┬►[notmuch] preliminary FreeBSD support (attachment, inbox, unread)
- 2009-11-17 Carl Worth ╰─► ... (inbox, unread)
+ 2010-12-29 François Boulogne ─►[aur-general] Guidelines: cp, mkdir vs install (inbox unread)
+ 2010-12-16 Olivier Berger ─►Essai accentué (inbox test_tag unread)
+ 2009-11-18 Chris Wilson ─►[notmuch] [PATCH 1/2] Makefile: evaluate pkg-config once (inbox unread)
+ 2009-11-18 Alex Botero-Lowry ┬►[notmuch] [PATCH] Error out if no query is supplied to search instead of going into an infinite loop (attachment inbox unread)
+ 2009-11-18 Carl Worth ╰─►[notmuch] [PATCH] Error out if no query is supplied to search instead of going into an infinite loop (inbox unread)
+ 2009-11-17 Ingmar Vanhassel ┬►[notmuch] [PATCH] Typsos (inbox unread)
+ 2009-11-18 Carl Worth ╰─► ... (inbox unread)
+ 2009-11-17 Adrian Perez de Cast ┬►[notmuch] Introducing myself (inbox signed unread)
+ 2009-11-18 Keith Packard ├─► ... (inbox unread)
+ 2009-11-18 Carl Worth ╰─► ... (inbox unread)
+ 2009-11-17 Israel Herraiz ┬►[notmuch] New to the list (inbox unread)
+ 2009-11-18 Keith Packard ├─► ... (inbox unread)
+ 2009-11-18 Carl Worth ╰─► ... (inbox unread)
+ 2009-11-17 Jan Janak ┬►[notmuch] What a great idea! (inbox unread)
+ 2009-11-17 Jan Janak ├─► ... (inbox unread)
+ 2009-11-18 Carl Worth ╰─► ... (inbox unread)
+ 2009-11-17 Jan Janak ┬►[notmuch] [PATCH] Older versions of install do not support -C. (inbox unread)
+ 2009-11-18 Carl Worth ╰─► ... (inbox unread)
+ 2009-11-17 Aron Griffis ┬►[notmuch] archive (inbox unread)
+ 2009-11-18 Keith Packard ╰┬► ... (inbox unread)
+ 2009-11-18 Carl Worth ╰─► ... (inbox unread)
+ 2009-11-17 Keith Packard ┬►[notmuch] [PATCH] Make notmuch-show 'X' (and 'x') commands remove inbox (and unread) tags (inbox unread)
+ 2009-11-18 Carl Worth ╰─►[notmuch] [PATCH] Make notmuch-show 'X' (and 'x') commands remove inbox (and unread) tags (inbox unread)
+ 2009-11-17 Lars Kellogg-Stedman ┬►[notmuch] Working with Maildir storage? (inbox signed unread)
+ 2009-11-17 Mikhail Gusarov ├┬► ... (inbox signed unread)
+ 2009-11-17 Lars Kellogg-Stedman │╰┬► ... (inbox signed unread)
+ 2009-11-17 Mikhail Gusarov │ ├─► ... (inbox unread)
+ 2009-11-17 Keith Packard │ ╰┬► ... (inbox unread)
+ 2009-11-18 Lars Kellogg-Stedman │ ╰─► ... (inbox signed unread)
+ 2009-11-18 Carl Worth ╰─► ... (inbox unread)
+ 2009-11-17 Mikhail Gusarov ┬►[notmuch] [PATCH 1/2] Close message file after parsing message headers (inbox unread)
+ 2009-11-17 Mikhail Gusarov ├─►[notmuch] [PATCH 2/2] Include <stdint.h> to get uint32_t in C++ file with gcc 4.4 (inbox unread)
+ 2009-11-17 Carl Worth ╰┬►[notmuch] [PATCH 1/2] Close message file after parsing message headers (inbox unread)
+ 2009-11-17 Keith Packard ╰┬► ... (inbox unread)
+ 2009-11-18 Carl Worth ╰─► ... (inbox unread)
+ 2009-11-18 Keith Packard ┬►[notmuch] [PATCH] Create a default notmuch-show-hook that highlights URLs and uses word-wrap (inbox unread)
+ 2009-11-18 Alexander Botero-Low ╰─►[notmuch] [PATCH] Create a default notmuch-show-hook that highlights URLs and uses word-wrap (inbox unread)
+ 2009-11-18 Alexander Botero-Low ─►[notmuch] request for pull (inbox unread)
+ 2009-11-18 Jjgod Jiang ┬►[notmuch] Mac OS X/Darwin compatibility issues (inbox unread)
+ 2009-11-18 Alexander Botero-Low ╰┬► ... (inbox unread)
+ 2009-11-18 Jjgod Jiang ╰┬► ... (inbox unread)
+ 2009-11-18 Alexander Botero-Low ╰─► ... (inbox unread)
+ 2009-11-18 Rolland Santimano ─►[notmuch] Link to mailing list archives ? (inbox unread)
+ 2009-11-18 Jan Janak ─►[notmuch] [PATCH] notmuch new: Support for conversion of spool subdirectories into tags (inbox unread)
+ 2009-11-18 Stewart Smith ─►[notmuch] [PATCH] count_files: sort directory in inode order before statting (inbox unread)
+ 2009-11-18 Stewart Smith ─►[notmuch] [PATCH 2/2] Read mail directory in inode number order (inbox unread)
+ 2009-11-18 Stewart Smith ─►[notmuch] [PATCH] Fix linking with gcc to use g++ to link in C++ libs. (inbox unread)
+ 2009-11-18 Lars Kellogg-Stedman ┬►[notmuch] "notmuch help" outputs to stderr? (attachment inbox signed unread)
+ 2009-11-18 Lars Kellogg-Stedman ╰─► ... (attachment inbox signed unread)
+ 2009-11-17 Mikhail Gusarov ─►[notmuch] [PATCH] Handle rename of message file (inbox unread)
+ 2009-11-17 Alex Botero-Lowry ┬►[notmuch] preliminary FreeBSD support (attachment inbox unread)
+ 2009-11-17 Carl Worth ╰─► ... (inbox unread)
End of search results.
- 2010-12-29 François Boulogne ─►[aur-general] Guidelines: cp, mkdir vs install (inbox, unread)
- 2010-12-16 Olivier Berger ─►Essai accentué (inbox, unread)
- 2009-11-18 Chris Wilson ─►[notmuch] [PATCH 1/2] Makefile: evaluate pkg-config once (inbox, unread)
- 2009-11-18 Alex Botero-Lowry ┬►[notmuch] [PATCH] Error out if no query is supplied to search instead of going into an infinite loop (attachment, inbox, unread)
- 2009-11-18 Carl Worth ╰─►[notmuch] [PATCH] Error out if no query is supplied to search instead of going into an infinite loop (inbox, unread)
- 2009-11-17 Ingmar Vanhassel ┬►[notmuch] [PATCH] Typsos (inbox, unread)
- 2009-11-18 Carl Worth ╰─► ... (inbox, unread)
- 2009-11-17 Adrian Perez de Cast ┬►[notmuch] Introducing myself (inbox, signed, unread)
- 2009-11-18 Keith Packard ├─► ... (inbox, unread)
- 2009-11-18 Carl Worth ╰─► ... (inbox, unread)
- 2009-11-17 Israel Herraiz ┬►[notmuch] New to the list (inbox, unread)
- 2009-11-18 Keith Packard ├─► ... (inbox, unread)
- 2009-11-18 Carl Worth ╰─► ... (inbox, unread)
- 2009-11-17 Jan Janak ┬►[notmuch] What a great idea! (inbox, unread)
- 2009-11-17 Jan Janak ├─► ... (inbox, unread)
- 2009-11-18 Carl Worth ╰─► ... (inbox, unread)
- 2009-11-17 Jan Janak ┬►[notmuch] [PATCH] Older versions of install do not support -C. (inbox, unread)
- 2009-11-18 Carl Worth ╰─► ... (inbox, unread)
- 2009-11-17 Aron Griffis ┬►[notmuch] archive (inbox, unread)
- 2009-11-18 Keith Packard ╰┬► ... (inbox, unread)
- 2009-11-18 Carl Worth ╰─► ... (inbox, unread)
- 2009-11-17 Keith Packard ┬►[notmuch] [PATCH] Make notmuch-show 'X' (and 'x') commands remove inbox (and unread) tags (inbox, unread)
- 2009-11-18 Carl Worth ╰─►[notmuch] [PATCH] Make notmuch-show 'X' (and 'x') commands remove inbox (and unread) tags (inbox, unread)
- 2009-11-17 Lars Kellogg-Stedman ┬►[notmuch] Working with Maildir storage? (inbox, signed, test_thread_tag, unread)
- 2009-11-17 Mikhail Gusarov ├┬► ... (inbox, signed, test_thread_tag, unread)
- 2009-11-17 Lars Kellogg-Stedman │╰┬► ... (inbox, signed, test_thread_tag, unread)
- 2009-11-17 Mikhail Gusarov │ ├─► ... (inbox, test_thread_tag, unread)
- 2009-11-17 Keith Packard │ ╰┬► ... (inbox, test_thread_tag, unread)
- 2009-11-18 Lars Kellogg-Stedman │ ╰─► ... (inbox, signed, test_thread_tag, unread)
- 2009-11-18 Carl Worth ╰─► ... (inbox, test_thread_tag, unread)
- 2009-11-17 Mikhail Gusarov ┬►[notmuch] [PATCH 1/2] Close message file after parsing message headers (inbox, unread)
- 2009-11-17 Mikhail Gusarov ├─►[notmuch] [PATCH 2/2] Include <stdint.h> to get uint32_t in C++ file with gcc 4.4 (inbox, unread)
- 2009-11-17 Carl Worth ╰┬►[notmuch] [PATCH 1/2] Close message file after parsing message headers (inbox, unread)
- 2009-11-17 Keith Packard ╰┬► ... (inbox, unread)
- 2009-11-18 Carl Worth ╰─► ... (inbox, unread)
- 2009-11-18 Keith Packard ┬►[notmuch] [PATCH] Create a default notmuch-show-hook that highlights URLs and uses word-wrap (inbox, unread)
- 2009-11-18 Alexander Botero-Low ╰─►[notmuch] [PATCH] Create a default notmuch-show-hook that highlights URLs and uses word-wrap (inbox, unread)
- 2009-11-18 Alexander Botero-Low ─►[notmuch] request for pull (inbox, unread)
- 2009-11-18 Jjgod Jiang ┬►[notmuch] Mac OS X/Darwin compatibility issues (inbox, unread)
- 2009-11-18 Alexander Botero-Low ╰┬► ... (inbox, unread)
- 2009-11-18 Jjgod Jiang ╰┬► ... (inbox, unread)
- 2009-11-18 Alexander Botero-Low ╰─► ... (inbox, unread)
- 2009-11-18 Rolland Santimano ─►[notmuch] Link to mailing list archives ? (inbox, unread)
- 2009-11-18 Jan Janak ─►[notmuch] [PATCH] notmuch new: Support for conversion of spool subdirectories into tags (inbox, unread)
- 2009-11-18 Stewart Smith ─►[notmuch] [PATCH] count_files: sort directory in inode order before statting (inbox, unread)
- 2009-11-18 Stewart Smith ─►[notmuch] [PATCH 2/2] Read mail directory in inode number order (inbox, unread)
- 2009-11-18 Stewart Smith ─►[notmuch] [PATCH] Fix linking with gcc to use g++ to link in C++ libs. (inbox, unread)
- 2009-11-18 Lars Kellogg-Stedman ┬►[notmuch] "notmuch help" outputs to stderr? (attachment, inbox, signed, unread)
- 2009-11-18 Lars Kellogg-Stedman ╰─► ... (attachment, inbox, signed, unread)
- 2009-11-17 Mikhail Gusarov ─►[notmuch] [PATCH] Handle rename of message file (inbox, unread)
- 2009-11-17 Alex Botero-Lowry ┬►[notmuch] preliminary FreeBSD support (attachment, inbox, unread)
- 2009-11-17 Carl Worth ╰─► ... (inbox, unread)
+ 2010-12-29 François Boulogne ─►[aur-general] Guidelines: cp, mkdir vs install (inbox unread)
+ 2010-12-16 Olivier Berger ─►Essai accentué (inbox unread)
+ 2009-11-18 Chris Wilson ─►[notmuch] [PATCH 1/2] Makefile: evaluate pkg-config once (inbox unread)
+ 2009-11-18 Alex Botero-Lowry ┬►[notmuch] [PATCH] Error out if no query is supplied to search instead of going into an infinite loop (attachment inbox unread)
+ 2009-11-18 Carl Worth ╰─►[notmuch] [PATCH] Error out if no query is supplied to search instead of going into an infinite loop (inbox unread)
+ 2009-11-17 Ingmar Vanhassel ┬►[notmuch] [PATCH] Typsos (inbox unread)
+ 2009-11-18 Carl Worth ╰─► ... (inbox unread)
+ 2009-11-17 Adrian Perez de Cast ┬►[notmuch] Introducing myself (inbox signed unread)
+ 2009-11-18 Keith Packard ├─► ... (inbox unread)
+ 2009-11-18 Carl Worth ╰─► ... (inbox unread)
+ 2009-11-17 Israel Herraiz ┬►[notmuch] New to the list (inbox unread)
+ 2009-11-18 Keith Packard ├─► ... (inbox unread)
+ 2009-11-18 Carl Worth ╰─► ... (inbox unread)
+ 2009-11-17 Jan Janak ┬►[notmuch] What a great idea! (inbox unread)
+ 2009-11-17 Jan Janak ├─► ... (inbox unread)
+ 2009-11-18 Carl Worth ╰─► ... (inbox unread)
+ 2009-11-17 Jan Janak ┬►[notmuch] [PATCH] Older versions of install do not support -C. (inbox unread)
+ 2009-11-18 Carl Worth ╰─► ... (inbox unread)
+ 2009-11-17 Aron Griffis ┬►[notmuch] archive (inbox unread)
+ 2009-11-18 Keith Packard ╰┬► ... (inbox unread)
+ 2009-11-18 Carl Worth ╰─► ... (inbox unread)
+ 2009-11-17 Keith Packard ┬►[notmuch] [PATCH] Make notmuch-show 'X' (and 'x') commands remove inbox (and unread) tags (inbox unread)
+ 2009-11-18 Carl Worth ╰─►[notmuch] [PATCH] Make notmuch-show 'X' (and 'x') commands remove inbox (and unread) tags (inbox unread)
+ 2009-11-17 Lars Kellogg-Stedman ┬►[notmuch] Working with Maildir storage? (inbox signed test_thread_tag unread)
+ 2009-11-17 Mikhail Gusarov ├┬► ... (inbox signed test_thread_tag unread)
+ 2009-11-17 Lars Kellogg-Stedman │╰┬► ... (inbox signed test_thread_tag unread)
+ 2009-11-17 Mikhail Gusarov │ ├─► ... (inbox test_thread_tag unread)
+ 2009-11-17 Keith Packard │ ╰┬► ... (inbox test_thread_tag unread)
+ 2009-11-18 Lars Kellogg-Stedman │ ╰─► ... (inbox signed test_thread_tag unread)
+ 2009-11-18 Carl Worth ╰─► ... (inbox test_thread_tag unread)
+ 2009-11-17 Mikhail Gusarov ┬►[notmuch] [PATCH 1/2] Close message file after parsing message headers (inbox unread)
+ 2009-11-17 Mikhail Gusarov ├─►[notmuch] [PATCH 2/2] Include <stdint.h> to get uint32_t in C++ file with gcc 4.4 (inbox unread)
+ 2009-11-17 Carl Worth ╰┬►[notmuch] [PATCH 1/2] Close message file after parsing message headers (inbox unread)
+ 2009-11-17 Keith Packard ╰┬► ... (inbox unread)
+ 2009-11-18 Carl Worth ╰─► ... (inbox unread)
+ 2009-11-18 Keith Packard ┬►[notmuch] [PATCH] Create a default notmuch-show-hook that highlights URLs and uses word-wrap (inbox unread)
+ 2009-11-18 Alexander Botero-Low ╰─►[notmuch] [PATCH] Create a default notmuch-show-hook that highlights URLs and uses word-wrap (inbox unread)
+ 2009-11-18 Alexander Botero-Low ─►[notmuch] request for pull (inbox unread)
+ 2009-11-18 Jjgod Jiang ┬►[notmuch] Mac OS X/Darwin compatibility issues (inbox unread)
+ 2009-11-18 Alexander Botero-Low ╰┬► ... (inbox unread)
+ 2009-11-18 Jjgod Jiang ╰┬► ... (inbox unread)
+ 2009-11-18 Alexander Botero-Low ╰─► ... (inbox unread)
+ 2009-11-18 Rolland Santimano ─►[notmuch] Link to mailing list archives ? (inbox unread)
+ 2009-11-18 Jan Janak ─►[notmuch] [PATCH] notmuch new: Support for conversion of spool subdirectories into tags (inbox unread)
+ 2009-11-18 Stewart Smith ─►[notmuch] [PATCH] count_files: sort directory in inode order before statting (inbox unread)
+ 2009-11-18 Stewart Smith ─►[notmuch] [PATCH 2/2] Read mail directory in inode number order (inbox unread)
+ 2009-11-18 Stewart Smith ─►[notmuch] [PATCH] Fix linking with gcc to use g++ to link in C++ libs. (inbox unread)
+ 2009-11-18 Lars Kellogg-Stedman ┬►[notmuch] "notmuch help" outputs to stderr? (attachment inbox signed unread)
+ 2009-11-18 Lars Kellogg-Stedman ╰─► ... (attachment inbox signed unread)
+ 2009-11-17 Mikhail Gusarov ─►[notmuch] [PATCH] Handle rename of message file (inbox unread)
+ 2009-11-17 Alex Botero-Lowry ┬►[notmuch] preliminary FreeBSD support (attachment inbox unread)
+ 2009-11-17 Carl Worth ╰─► ... (inbox unread)
End of search results.
+++ /dev/null
-#!/usr/bin/env bash
-test_description="handling of uuencoded data"
-. ./test-lib.sh
-
-add_message [subject]=uuencodetest '[date]="Sat, 01 Jan 2000 12:00:00 -0000"' \
-'[body]="This message is used to ensure that notmuch correctly handles a
-message containing a block of uuencoded data. First, we have a marker
-this content beforeuudata . Then we begin the uuencoded data itself:
-
-begin 644 bogus-uuencoded-data
-M0123456789012345678901234567890123456789012345678901234567890
-MOBVIOUSLY, THIS IS NOT ANY SORT OF USEFUL UUENCODED DATA.
-MINSTEAD THIS IS JUST A WAY TO ENSURE THAT THIS BLOCK OF DATA
-MIS CORRECTLY IGNORED WHEN NOTMUCH CREATES ITS INDEX. SO WE
-MINCLUDE A DURINGUUDATA MARKER THAT SHOULD NOT RESULT IN ANY
-MSEARCH RESULT.
-\\\`
-end
-
-Finally, we have our afteruudata marker as well."'
-
-test_begin_subtest "Ensure content before uu data is indexed"
-output=$(notmuch search beforeuudata | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; uuencodetest (inbox unread)"
-
-test_begin_subtest "Ensure uu data is not indexed"
-output=$(notmuch search DURINGUUDATA | notmuch_search_sanitize)
-test_expect_equal "$output" ""
-
-test_begin_subtest "Ensure content after uu data is indexed"
-output=$(notmuch search afteruudata | notmuch_search_sanitize)
-test_expect_equal "$output" "thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; uuencodetest (inbox unread)"
-
-test_done