From 15ea8625d1895a376c18c23845a774f32eb7aece Mon Sep 17 00:00:00 2001 From: Mark Walters Date: Sat, 14 Jan 2012 16:46:19 +0200 Subject: test: add tests for "notmuch reply" --reply-to=sender --- test/notmuch-test | 1 + test/reply-to-sender | 209 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 210 insertions(+) create mode 100755 test/reply-to-sender (limited to 'test') diff --git a/test/notmuch-test b/test/notmuch-test index e40ef86..6a99ae3 100755 --- a/test/notmuch-test +++ b/test/notmuch-test @@ -33,6 +33,7 @@ TESTS=" thread-naming raw reply + reply-to-sender dump-restore uuencode thread-order diff --git a/test/reply-to-sender b/test/reply-to-sender new file mode 100755 index 0000000..c7d15bb --- /dev/null +++ b/test/reply-to-sender @@ -0,0 +1,209 @@ +#!/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 "' \ + [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 +Subject: Re: notmuch-reply-test +To: Sender +In-Reply-To: <${gen_msg_id}> +References: <${gen_msg_id}> + +On Tue, 05 Jan 2010 15:43:56 -0000, Sender wrote: +> basic reply-to-sender test" + +test_begin_subtest "From Us, Basic reply to message" +add_message '[from]="Notmuch Test Suite "' \ + '[to]="Recipient "' \ + [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 +Subject: Re: notmuch-reply-test +To: Recipient +In-Reply-To: <${gen_msg_id}> +References: <${gen_msg_id}> + +On Tue, 05 Jan 2010 15:43:56 -0000, Notmuch Test Suite wrote: +> basic reply-to-from-us test" + +test_begin_subtest "Multiple recipients" +add_message '[from]="Sender "' \ + '[to]="test_suite@notmuchmail.org, Someone Else "' \ + [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 +Subject: Re: notmuch-reply-test +To: Sender +In-Reply-To: <${gen_msg_id}> +References: <${gen_msg_id}> + +On Tue, 05 Jan 2010 15:43:56 -0000, Sender wrote: +> Multiple recipients" + +test_begin_subtest "From Us, Multiple TO recipients" +add_message '[from]="Notmuch Test Suite "' \ + '[to]="Recipient , Someone Else "' \ + [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 +Subject: Re: notmuch-reply-test +To: Recipient , Someone Else +In-Reply-To: <${gen_msg_id}> +References: <${gen_msg_id}> + +On Tue, 05 Jan 2010 15:43:56 -0000, Notmuch Test Suite wrote: +> From Us, Multiple TO recipients" + +test_begin_subtest "Reply with CC" +add_message '[from]="Sender "' \ + [to]=test_suite@notmuchmail.org \ + '[cc]="Other Parties "' \ + [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 +Subject: Re: notmuch-reply-test +To: Sender +In-Reply-To: <${gen_msg_id}> +References: <${gen_msg_id}> + +On Tue, 05 Jan 2010 15:43:56 -0000, Sender wrote: +> reply with CC" + +test_begin_subtest "From Us, Reply with CC" +add_message '[from]="Notmuch Test Suite "' \ + '[to]="Recipient "' \ + '[cc]="Other Parties "' \ + [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 +Subject: Re: notmuch-reply-test +To: Recipient +In-Reply-To: <${gen_msg_id}> +References: <${gen_msg_id}> + +On Tue, 05 Jan 2010 15:43:56 -0000, Notmuch Test Suite wrote: +> reply with CC" + +test_begin_subtest "From Us, Reply no TO but with CC" +add_message '[from]="Notmuch Test Suite "' \ + '[cc]="Other Parties "' \ + [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 +Subject: Re: notmuch-reply-test +Cc: Other Parties +In-Reply-To: <${gen_msg_id}> +References: <${gen_msg_id}> + +On Tue, 05 Jan 2010 15:43:56 -0000, Notmuch Test Suite wrote: +> reply with CC" + +test_begin_subtest "Reply from alternate address" +add_message '[from]="Sender "' \ + [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 +Subject: Re: notmuch-reply-test +To: Sender +In-Reply-To: <${gen_msg_id}> +References: <${gen_msg_id}> + +On Tue, 05 Jan 2010 15:43:56 -0000, Sender wrote: +> reply from alternate address" + +test_begin_subtest "Support for Reply-To" +add_message '[from]="Sender "' \ + [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 "' + +output=$(notmuch reply --reply-to=sender id:${gen_msg_id}) +test_expect_equal "$output" "From: Notmuch Test Suite +Subject: Re: notmuch-reply-test +To: Sender +In-Reply-To: <${gen_msg_id}> +References: <${gen_msg_id}> + +On Tue, 05 Jan 2010 15:43:56 -0000, Sender wrote: +> support for reply-to" + +test_begin_subtest "Support for Reply-To with multiple recipients" +add_message '[from]="Sender "' \ + '[to]="test_suite@notmuchmail.org, Someone Else "' \ + [subject]=notmuch-reply-test \ + '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \ + '[body]="support for reply-to with multiple recipients"' \ + '[reply-to]="Sender "' + +output=$(notmuch reply --reply-to=sender id:${gen_msg_id}) +test_expect_equal "$output" "From: Notmuch Test Suite +Subject: Re: notmuch-reply-test +To: Sender +In-Reply-To: <${gen_msg_id}> +References: <${gen_msg_id}> + +On Tue, 05 Jan 2010 15:43:56 -0000, Sender wrote: +> support for reply-to with multiple recipients" + +test_begin_subtest "Un-munging Reply-To" +add_message '[from]="Sender "' \ + '[to]="Some List "' \ + [subject]=notmuch-reply-test \ + '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \ + '[body]="Un-munging Reply-To"' \ + '[reply-to]="Evil Munging List "' + +output=$(notmuch reply --reply-to=sender id:${gen_msg_id}) +test_expect_equal "$output" "From: Notmuch Test Suite +Subject: Re: notmuch-reply-test +To: Sender +In-Reply-To: <${gen_msg_id}> +References: <${gen_msg_id}> + +On Tue, 05 Jan 2010 15:43:56 -0000, Sender 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 +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 wrote: +> 200-byte header" +test_done -- cgit v1.2.3 From 42e8f66edf91095bb87b3ee7713b94002ffd3edc Mon Sep 17 00:00:00 2001 From: Pieter Praet Date: Sat, 14 Jan 2012 10:09:37 +0100 Subject: test: don't bail out of `run_emacs' too early when missing prereqs When running the Emacs tests in verbose mode, only the first missing prereq is reported because the `run_emacs' function is short-circuited early: #+begin_example emacs: Testing emacs interface missing prerequisites: [0] emacs(1) skipping test: [0] Basic notmuch-hello view in emacs SKIP [0] Basic notmuch-hello view in emacs #+end_example This can lead to situations reminiscent of "dependency hell", so instead of returning based on each individual `test_require_external_prereq's exit status, we now do so only after checking all the prereqs: #+begin_example emacs: Testing emacs interface missing prerequisites: [0] dtach(1) emacs(1) emacsclient(1) skipping test: [0] Basic notmuch-hello view in emacs SKIP [0] Basic notmuch-hello view in emacs #+end_example Also added missing prereq for dtach(1). --- test/test-lib.sh | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'test') diff --git a/test/test-lib.sh b/test/test-lib.sh index 82767c0..d1fbc05 100644 --- a/test/test-lib.sh +++ b/test/test-lib.sh @@ -907,8 +907,11 @@ EOF test_emacs () { # test dependencies beforehand to avoid the waiting loop below - test_require_external_prereq emacs || return - test_require_external_prereq emacsclient || return + missing_dependencies= + test_require_external_prereq dtach || missing_dependencies=1 + test_require_external_prereq emacs || missing_dependencies=1 + test_require_external_prereq emacsclient || missing_dependencies=1 + test -z "$missing_dependencies" || return if [ -z "$EMACS_SERVER" ]; then server_name="notmuch-test-suite-$$" -- cgit v1.2.3 From 93150f6467e10d075bf5cf4f27eb632a4d5d63dd Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Sat, 14 Jan 2012 23:49:49 +0200 Subject: test: add known broken test for reply from address in named group list If a message was received to the user's address that was in a named group list, notmuch reply does not use that address for picking the from address. Groups lists are of the form: foo:bar@example.com,baz@example.com; Signed-off-by: Jani Nikula --- test/reply | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'test') diff --git a/test/reply b/test/reply index c0b8e26..196535a 100755 --- a/test/reply +++ b/test/reply @@ -72,6 +72,25 @@ References: <${gen_msg_id}> On Tue, 05 Jan 2010 15:43:56 -0000, Sender wrote: > reply from alternate address" +test_begin_subtest "Reply from address in named group list" +test_subtest_known_broken +add_message '[from]="Sender "' \ + '[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 +Subject: Re: notmuch-reply-test +To: Sender , someone@example.com +In-Reply-To: <${gen_msg_id}> +References: <${gen_msg_id}> + +On Tue, 05 Jan 2010 15:43:56 -0000, Sender wrote: +> Reply from address in named group list" + test_begin_subtest "Support for Reply-To" add_message '[from]="Sender "' \ [to]=test_suite@notmuchmail.org \ -- cgit v1.2.3 From 982096d79df8d47ac62d9a74fa0a9baa9c008812 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Sat, 14 Jan 2012 23:49:50 +0200 Subject: cli: pick the user's address in a group list as from address Messages received to a group list were not replied to using the from address in the list. Fix it. Signed-off-by: Jani Nikula --- notmuch-reply.c | 2 +- test/reply | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'test') diff --git a/notmuch-reply.c b/notmuch-reply.c index da3acce..0f682db 100644 --- a/notmuch-reply.c +++ b/notmuch-reply.c @@ -203,7 +203,7 @@ scan_address_list (InternetAddressList *list, if (group_list == NULL) continue; - n += scan_address_list (group_list, config, message, type, NULL); + n += scan_address_list (group_list, config, message, type, user_from); } else { InternetAddressMailbox *mailbox; const char *name; diff --git a/test/reply b/test/reply index 196535a..e4e16eb 100755 --- a/test/reply +++ b/test/reply @@ -73,7 +73,6 @@ On Tue, 05 Jan 2010 15:43:56 -0000, Sender wrote: > reply from alternate address" test_begin_subtest "Reply from address in named group list" -test_subtest_known_broken add_message '[from]="Sender "' \ '[to]=group:test_suite@notmuchmail.org,someone@example.com\;' \ [cc]=test_suite_other@notmuchmail.org \ -- cgit v1.2.3 From 42a907992823030f070fc395a174f779998ca6f5 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Sat, 14 Jan 2012 19:17:34 -0500 Subject: search: Support automatic tag exclusions This adds a "search" section to the config file and an "auto_tag_exclusions" setting in that section. The search and count commands pass tag tags from the configuration to the library. --- notmuch-client.h | 8 ++++++++ notmuch-config.c | 42 ++++++++++++++++++++++++++++++++++++++++++ notmuch-count.c | 8 ++++++++ notmuch-search.c | 8 ++++++++ test/search | 18 ++++++++++++++++++ 5 files changed, 84 insertions(+) (limited to 'test') diff --git a/notmuch-client.h b/notmuch-client.h index 517c010..62ede28 100644 --- a/notmuch-client.h +++ b/notmuch-client.h @@ -235,6 +235,14 @@ void notmuch_config_set_maildir_synchronize_flags (notmuch_config_t *config, notmuch_bool_t synchronize_flags); +const char ** +notmuch_config_get_auto_exclude_tags (notmuch_config_t *config, size_t *length); + +void +notmuch_config_set_auto_exclude_tags (notmuch_config_t *config, + const char *list[], + size_t length); + int notmuch_run_hook (const char *db_path, const char *hook); diff --git a/notmuch-config.c b/notmuch-config.c index d697138..3d4d5b9 100644 --- a/notmuch-config.c +++ b/notmuch-config.c @@ -84,6 +84,15 @@ static const char maildir_config_comment[] = "\tand update tags, while the \"notmuch tag\" and \"notmuch restore\"\n" "\tcommands will notice tag changes and update flags in filenames\n"; +static const char search_config_comment[] = + " Search configuration\n" + "\n" + " The following option is supported here:\n" + "\n" + "\tauto_exclude_tags A ;-separated list of tags that will be\n" + "\t excluded from search results by default. Using an excluded tag\n" + "\t in a query will override that exclusion.\n"; + struct _notmuch_config { char *filename; GKeyFile *key_file; @@ -96,6 +105,8 @@ struct _notmuch_config { const char **new_tags; size_t new_tags_length; notmuch_bool_t maildir_synchronize_flags; + const char **auto_exclude_tags; + size_t auto_exclude_tags_length; }; static int @@ -221,6 +232,7 @@ notmuch_config_open (void *ctx, int file_had_new_group; int file_had_user_group; int file_had_maildir_group; + int file_had_search_group; if (is_new_ret) *is_new_ret = 0; @@ -252,6 +264,8 @@ notmuch_config_open (void *ctx, config->new_tags = NULL; config->new_tags_length = 0; config->maildir_synchronize_flags = TRUE; + config->auto_exclude_tags = NULL; + config->auto_exclude_tags_length = 0; if (! g_key_file_load_from_file (config->key_file, config->filename, @@ -295,6 +309,7 @@ notmuch_config_open (void *ctx, file_had_new_group = g_key_file_has_group (config->key_file, "new"); file_had_user_group = g_key_file_has_group (config->key_file, "user"); file_had_maildir_group = g_key_file_has_group (config->key_file, "maildir"); + file_had_search_group = g_key_file_has_group (config->key_file, "search"); if (notmuch_config_get_database_path (config) == NULL) { @@ -345,6 +360,11 @@ notmuch_config_open (void *ctx, notmuch_config_set_new_tags (config, tags, 2); } + if (notmuch_config_get_auto_exclude_tags (config, &tmp) == NULL) { + const char *tags[] = { "deleted", "spam" }; + notmuch_config_set_auto_exclude_tags (config, tags, 2); + } + error = NULL; config->maildir_synchronize_flags = g_key_file_get_boolean (config->key_file, @@ -387,6 +407,11 @@ notmuch_config_open (void *ctx, maildir_config_comment, NULL); } + if (! file_had_search_group) { + g_key_file_set_comment (config->key_file, "search", NULL, + search_config_comment, NULL); + } + if (is_new_ret) *is_new_ret = is_new; @@ -597,6 +622,23 @@ notmuch_config_set_new_tags (notmuch_config_t *config, &(config->new_tags)); } +const char ** +notmuch_config_get_auto_exclude_tags (notmuch_config_t *config, size_t *length) +{ + return _config_get_list (config, "search", "auto_exclude_tags", + &(config->auto_exclude_tags), + &(config->auto_exclude_tags_length), length); +} + +void +notmuch_config_set_auto_exclude_tags (notmuch_config_t *config, + const char *list[], + size_t length) +{ + _config_set_list (config, "search", "auto_exclude_tags", list, length, + &(config->auto_exclude_tags)); +} + /* Given a configuration item of the form . return the * component group and key. If any error occurs, print a message on * stderr and return 1. Otherwise, return 0. diff --git a/notmuch-count.c b/notmuch-count.c index 0982f99..f77861e 100644 --- a/notmuch-count.c +++ b/notmuch-count.c @@ -35,6 +35,9 @@ notmuch_count_command (void *ctx, int argc, char *argv[]) char *query_str; int opt_index; int output = OUTPUT_MESSAGES; + const char **auto_exclude_tags; + size_t auto_exclude_tags_length; + unsigned int i; notmuch_opt_desc_t options[] = { { NOTMUCH_OPT_KEYWORD, &output, "output", 'o', @@ -75,6 +78,11 @@ notmuch_count_command (void *ctx, int argc, char *argv[]) return 1; } + auto_exclude_tags = notmuch_config_get_auto_exclude_tags + (config, &auto_exclude_tags_length); + for (i = 0; i < auto_exclude_tags_length; i++) + notmuch_query_add_tag_exclude (query, auto_exclude_tags[i]); + switch (output) { case OUTPUT_MESSAGES: printf ("%u\n", notmuch_query_count_messages (query)); diff --git a/notmuch-search.c b/notmuch-search.c index 4baab56..8867aab 100644 --- a/notmuch-search.c +++ b/notmuch-search.c @@ -423,6 +423,9 @@ notmuch_search_command (void *ctx, int argc, char *argv[]) output_t output = OUTPUT_SUMMARY; int offset = 0; int limit = -1; /* unlimited */ + const char **auto_exclude_tags; + size_t auto_exclude_tags_length; + unsigned int i; enum { NOTMUCH_FORMAT_JSON, NOTMUCH_FORMAT_TEXT } format_sel = NOTMUCH_FORMAT_TEXT; @@ -490,6 +493,11 @@ notmuch_search_command (void *ctx, int argc, char *argv[]) notmuch_query_set_sort (query, sort); + auto_exclude_tags = notmuch_config_get_auto_exclude_tags + (config, &auto_exclude_tags_length); + for (i = 0; i < auto_exclude_tags_length; i++) + notmuch_query_add_tag_exclude (query, auto_exclude_tags[i]); + switch (output) { default: case OUTPUT_SUMMARY: diff --git a/test/search b/test/search index a7a0b18..bf965e7 100755 --- a/test/search +++ b/test/search @@ -129,4 +129,22 @@ add_message '[subject]="utf8-message-body-subject"' '[date]="Sat, 01 Jan 2000 12 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_begin_subtest "Exclude \"deleted\" messages from search" +generate_message '[subject]="Not deleted"' +generate_message '[subject]="Deleted"' +notmuch new > /dev/null +notmuch tag +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 "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 "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_done -- cgit v1.2.3 From 5c12ee4b5d942b5c9efc79922d25b1cf9934aab0 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Sun, 15 Jan 2012 15:20:42 -0500 Subject: Fix dependency generation for compat, test, and util This adds source files in compat, test, and util to SRCS so that the top-level Makefile.local will generate dependency files for them. --- compat/Makefile.local | 2 ++ test/Makefile.local | 1 + util/Makefile.local | 1 + 3 files changed, 4 insertions(+) (limited to 'test') diff --git a/compat/Makefile.local b/compat/Makefile.local index 504eb71..13f16cd 100644 --- a/compat/Makefile.local +++ b/compat/Makefile.local @@ -12,3 +12,5 @@ endif ifneq ($(HAVE_STRCASESTR),1) notmuch_compat_srcs += $(dir)/strcasestr.c endif + +SRCS := $(SRCS) $(notmuch_compat_srcs) diff --git a/test/Makefile.local b/test/Makefile.local index fa2df73..4a6a4b1 100644 --- a/test/Makefile.local +++ b/test/Makefile.local @@ -28,6 +28,7 @@ test: all test-binaries check: test +SRCS := $(SRCS) $(smtp_dummy_srcs) CLEAN := $(CLEAN) $(dir)/smtp-dummy $(dir)/smtp-dummy.o \ $(dir)/symbol-test $(dir)/symbol-test.o \ $(dir)/arg-test $(dir)/arg-test.o diff --git a/util/Makefile.local b/util/Makefile.local index 26e4c3f..c7cae61 100644 --- a/util/Makefile.local +++ b/util/Makefile.local @@ -10,4 +10,5 @@ libutil_modules := $(libutil_c_srcs:.c=.o) $(dir)/libutil.a: $(libutil_modules) $(call quiet,AR) rcs $@ $^ +SRCS := $(SRCS) $(libutil_c_srcs) CLEAN := $(CLEAN) $(libutil_modules) $(dir)/libutil.a -- cgit v1.2.3 From 8ae753f30fb90419c50b9bb1fc87618dd1663bc9 Mon Sep 17 00:00:00 2001 From: Ethan Glasser-Camp Date: Mon, 16 Jan 2012 13:52:47 -0500 Subject: Document external dependencies in the test suite Add an explicit note to the README explaining what programs are necessary and the perhaps-surprising behavior of skipping tests if they aren't present. Signed-off-by: Ethan Glasser-Camp --- test/README | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'test') diff --git a/test/README b/test/README index bde6db0..44ff653 100644 --- a/test/README +++ b/test/README @@ -6,6 +6,19 @@ When fixing bugs or enhancing notmuch, you are strongly encouraged to add tests in this directory to cover what you are trying to fix or enhance. +Prerequisites +------------- +Some tests require external dependencies to run. Without them, they +will be skipped, or (rarely) marked failed. Please install these, so +that you know if you break anything. + + - dtach(1) + - emacs(1) + - emacsclient(1) + - gdb(1) + - gpg(1) + - python(1) + Running Tests ------------- The easiest way to run tests is to say "make test", (or simply run the -- cgit v1.2.3 From d3aa6848da4519f6229426b1d0432afacf748f8b Mon Sep 17 00:00:00 2001 From: Dmitry Kurochkin Date: Fri, 20 Jan 2012 00:52:14 +0100 Subject: emacs: add invisible dot instead of space at the end of notmuch-hello search box This makes `show-trailing-whitespace' happy, i.e. it does not mark the whole search box line as trailing spaces. Since the dot is invisible, this change makes no visible difference for `notmuch-hello'. Edited-by: Pieter Praet to fix the tests. --- emacs/notmuch-hello.el | 9 ++++++--- test/emacs.expected-output/notmuch-hello | 2 +- test/emacs.expected-output/notmuch-hello-no-saved-searches | 2 +- test/emacs.expected-output/notmuch-hello-with-empty | 2 +- 4 files changed, 9 insertions(+), 6 deletions(-) (limited to 'test') diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el index ba48cd6..1a61768 100644 --- a/emacs/notmuch-hello.el +++ b/emacs/notmuch-hello.el @@ -511,9 +511,12 @@ Complete list of currently available key bindings: (length "Search: "))) :action (lambda (widget &rest ignore) (notmuch-hello-search (widget-value widget)))) - ;; add an invisible space to make `widget-end-of-line' ignore - ;; trailine spaces in the search widget field - (widget-insert " ") + ;; Add an invisible dot to make `widget-end-of-line' ignore + ;; trailing spaces in the search widget field. A dot is used + ;; instead of a space to make `show-trailing-whitespace' + ;; happy, i.e. avoid it marking the whole line as trailing + ;; spaces. + (widget-insert ".") (put-text-property (1- (point)) (point) 'invisible t) (widget-insert "\n") diff --git a/test/emacs.expected-output/notmuch-hello b/test/emacs.expected-output/notmuch-hello index de57de2..196112e 100644 --- a/test/emacs.expected-output/notmuch-hello +++ b/test/emacs.expected-output/notmuch-hello @@ -4,7 +4,7 @@ Saved searches: [edit] 52 inbox 52 unread -Search: +Search: . [Show all tags] diff --git a/test/emacs.expected-output/notmuch-hello-no-saved-searches b/test/emacs.expected-output/notmuch-hello-no-saved-searches index f1fc4d6..f4cfe49 100644 --- a/test/emacs.expected-output/notmuch-hello-no-saved-searches +++ b/test/emacs.expected-output/notmuch-hello-no-saved-searches @@ -1,6 +1,6 @@ Welcome to notmuch. You have 52 messages. -Search: +Search: . [Show all tags] diff --git a/test/emacs.expected-output/notmuch-hello-with-empty b/test/emacs.expected-output/notmuch-hello-with-empty index dd8728b..a860a72 100644 --- a/test/emacs.expected-output/notmuch-hello-with-empty +++ b/test/emacs.expected-output/notmuch-hello-with-empty @@ -4,7 +4,7 @@ Saved searches: [edit] 52 inbox 52 unread 0 empty -Search: +Search: . [Show all tags] -- cgit v1.2.3 From 00b5623d1a21d886b564d031e30749e5d02e4ae6 Mon Sep 17 00:00:00 2001 From: Thomas Jost Date: Fri, 20 Jan 2012 10:39:24 +0100 Subject: Add compatibility with gmime 2.6 There are lots of API changes in gmime 2.6 crypto handling. By adding preprocessor directives, it is however possible to add gmime 2.6 compatibility while preserving compatibility with gmime 2.4 too. This is mostly based on id:"8762i8hrb9.fsf@bookbinder.fernseed.info". This was tested against both gmime 2.6.4 and 2.4.31. With gmime 2.4.31, the crypto tests all work fine (as expected). With gmime 2.6.4, one crypto test is currently broken (signature verification with signer key unavailable), most likely because of a bug in gmime which will hopefully be fixed in a future version. --- mime-node.c | 57 ++++++++++++++++++++++++++++++++-- notmuch-client.h | 30 ++++++++++++++++-- notmuch-reply.c | 7 +++++ notmuch-show.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ show-message.c | 4 +++ test/crypto | 2 ++ 6 files changed, 191 insertions(+), 4 deletions(-) (limited to 'test') diff --git a/mime-node.c b/mime-node.c index d26bb44..27077f7 100644 --- a/mime-node.c +++ b/mime-node.c @@ -33,7 +33,11 @@ typedef struct mime_node_context { GMimeMessage *mime_message; /* Context provided by the caller. */ +#ifdef GMIME_ATLEAST_26 + GMimeCryptoContext *cryptoctx; +#else GMimeCipherContext *cryptoctx; +#endif notmuch_bool_t decrypt; } mime_node_context_t; @@ -57,8 +61,12 @@ _mime_node_context_free (mime_node_context_t *res) notmuch_status_t mime_node_open (const void *ctx, notmuch_message_t *message, - GMimeCipherContext *cryptoctx, notmuch_bool_t decrypt, - mime_node_t **root_out) +#ifdef GMIME_ATLEAST_26 + GMimeCryptoContext *cryptoctx, +#else + GMimeCipherContext *cryptoctx, +#endif + notmuch_bool_t decrypt, mime_node_t **root_out) { const char *filename = notmuch_message_get_filename (message); mime_node_context_t *mctx; @@ -112,12 +120,21 @@ DONE: return status; } +#ifdef GMIME_ATLEAST_26 +static int +_signature_list_free (GMimeSignatureList **proxy) +{ + g_object_unref (*proxy); + return 0; +} +#else static int _signature_validity_free (GMimeSignatureValidity **proxy) { g_mime_signature_validity_free (*proxy); return 0; } +#endif static mime_node_t * _mime_node_create (const mime_node_t *parent, GMimeObject *part) @@ -165,11 +182,25 @@ _mime_node_create (const mime_node_t *parent, GMimeObject *part) GMimeMultipartEncrypted *encrypteddata = GMIME_MULTIPART_ENCRYPTED (part); node->decrypt_attempted = TRUE; +#ifdef GMIME_ATLEAST_26 + GMimeDecryptResult *decrypt_result = NULL; + node->decrypted_child = g_mime_multipart_encrypted_decrypt + (encrypteddata, node->ctx->cryptoctx, &decrypt_result, &err); +#else node->decrypted_child = g_mime_multipart_encrypted_decrypt (encrypteddata, node->ctx->cryptoctx, &err); +#endif if (node->decrypted_child) { node->decrypt_success = node->verify_attempted = TRUE; +#ifdef GMIME_ATLEAST_26 + /* This may be NULL if the part is not signed. */ + node->sig_list = g_mime_decrypt_result_get_signatures (decrypt_result); + if (node->sig_list) + g_object_ref (node->sig_list); + g_object_unref (decrypt_result); +#else node->sig_validity = g_mime_multipart_encrypted_get_signature_validity (encrypteddata); +#endif } else { fprintf (stderr, "Failed to decrypt part: %s\n", (err ? err->message : "no error explanation given")); @@ -182,6 +213,15 @@ _mime_node_create (const mime_node_t *parent, GMimeObject *part) "(must be exactly 2)\n", node->nchildren); } else { +#ifdef GMIME_ATLEAST_26 + node->sig_list = g_mime_multipart_signed_verify + (GMIME_MULTIPART_SIGNED (part), node->ctx->cryptoctx, &err); + node->verify_attempted = TRUE; + + if (!node->sig_list) + fprintf (stderr, "Failed to verify signed part: %s\n", + (err ? err->message : "no error explanation given")); +#else /* For some reason the GMimeSignatureValidity returned * here is not a const (inconsistent with that * returned by @@ -200,12 +240,25 @@ _mime_node_create (const mime_node_t *parent, GMimeObject *part) *proxy = sig_validity; talloc_set_destructor (proxy, _signature_validity_free); } +#endif } } +#ifdef GMIME_ATLEAST_26 + /* sig_list may be created in both above cases, so we need to + * cleanly handle it here. */ + if (node->sig_list) { + GMimeSignatureList **proxy = talloc (node, GMimeSignatureList *); + *proxy = node->sig_list; + talloc_set_destructor (proxy, _signature_list_free); + } +#endif + +#ifndef GMIME_ATLEAST_26 if (node->verify_attempted && !node->sig_validity) fprintf (stderr, "Failed to verify signed part: %s\n", (err ? err->message : "no error explanation given")); +#endif if (err) g_error_free (err); diff --git a/notmuch-client.h b/notmuch-client.h index 62ede28..9c1d383 100644 --- a/notmuch-client.h +++ b/notmuch-client.h @@ -30,6 +30,14 @@ #include +/* GMIME_CHECK_VERSION in gmime 2.4 is not usable from the + * preprocessor (it calls a runtime function). But since + * GMIME_MAJOR_VERSION and friends were added in gmime 2.6, we can use + * these to check the version number. */ +#ifdef GMIME_MAJOR_VERSION +#define GMIME_ATLEAST_26 +#endif + #include "notmuch.h" /* This is separate from notmuch-private.h because we're trying to @@ -69,7 +77,11 @@ typedef struct notmuch_show_format { void (*part_start) (GMimeObject *part, int *part_count); void (*part_encstatus) (int status); +#ifdef GMIME_ATLEAST_26 + void (*part_sigstatus) (GMimeSignatureList* siglist); +#else void (*part_sigstatus) (const GMimeSignatureValidity* validity); +#endif void (*part_content) (GMimeObject *part); void (*part_end) (GMimeObject *part); const char *part_sep; @@ -83,7 +95,11 @@ typedef struct notmuch_show_params { int entire_thread; int raw; int part; +#ifdef GMIME_ATLEAST_26 + GMimeCryptoContext* cryptoctx; +#else GMimeCipherContext* cryptoctx; +#endif int decrypt; } notmuch_show_params_t; @@ -290,11 +306,17 @@ typedef struct mime_node { /* True if signature verification on this part was attempted. */ notmuch_bool_t verify_attempted; +#ifdef GMIME_ATLEAST_26 + /* The list of signatures for signed or encrypted containers. If + * there are no signatures, this will be NULL. */ + GMimeSignatureList* sig_list; +#else /* For signed or encrypted containers, the validity of the * signature. May be NULL if signature verification failed. If * there are simply no signatures, this will be non-NULL with an * empty signers list. */ const GMimeSignatureValidity *sig_validity; +#endif /* Internal: Context inherited from the root iterator. */ struct mime_node_context *ctx; @@ -319,8 +341,12 @@ typedef struct mime_node { */ notmuch_status_t mime_node_open (const void *ctx, notmuch_message_t *message, - GMimeCipherContext *cryptoctx, notmuch_bool_t decrypt, - mime_node_t **node_out); +#ifdef GMIME_ATLEAST_26 + GMimeCryptoContext *cryptoctx, +#else + GMimeCipherContext *cryptoctx, +#endif + notmuch_bool_t decrypt, mime_node_t **node_out); /* Return a new MIME node for the requested child part of parent. * parent will be used as the talloc context for the returned child diff --git a/notmuch-reply.c b/notmuch-reply.c index 0f682db..bf67960 100644 --- a/notmuch-reply.c +++ b/notmuch-reply.c @@ -688,15 +688,22 @@ notmuch_reply_command (void *ctx, int argc, char *argv[]) reply_format_func = notmuch_reply_format_default; if (decrypt) { +#ifdef GMIME_ATLEAST_26 + /* TODO: GMimePasswordRequestFunc */ + params.cryptoctx = g_mime_gpg_context_new (NULL, "gpg"); +#else GMimeSession* session = g_object_new (g_mime_session_get_type(), NULL); params.cryptoctx = g_mime_gpg_context_new (session, "gpg"); +#endif if (params.cryptoctx) { g_mime_gpg_context_set_always_trust ((GMimeGpgContext*) params.cryptoctx, FALSE); params.decrypt = TRUE; } else { fprintf (stderr, "Failed to construct gpg context.\n"); } +#ifndef GMIME_ATLEAST_26 g_object_unref (session); +#endif } config = notmuch_config_open (ctx, NULL, NULL); diff --git a/notmuch-show.c b/notmuch-show.c index c674e25..43ee211 100644 --- a/notmuch-show.c +++ b/notmuch-show.c @@ -76,7 +76,11 @@ static void format_part_encstatus_json (int status); static void +#ifdef GMIME_ATLEAST_26 +format_part_sigstatus_json (GMimeSignatureList* siglist); +#else format_part_sigstatus_json (const GMimeSignatureValidity* validity); +#endif static void format_part_content_json (GMimeObject *part); @@ -486,6 +490,21 @@ show_text_part_content (GMimeObject *part, GMimeStream *stream_out) g_object_unref(stream_filter); } +#ifdef GMIME_ATLEAST_26 +static const char* +signature_status_to_string (GMimeSignatureStatus x) +{ + switch (x) { + case GMIME_SIGNATURE_STATUS_GOOD: + return "good"; + case GMIME_SIGNATURE_STATUS_BAD: + return "bad"; + case GMIME_SIGNATURE_STATUS_ERROR: + return "error"; + } + return "unknown"; +} +#else static const char* signer_status_to_string (GMimeSignerStatus x) { @@ -501,6 +520,7 @@ signer_status_to_string (GMimeSignerStatus x) } return "unknown"; } +#endif static void format_part_start_text (GMimeObject *part, int *part_count) @@ -592,6 +612,73 @@ format_part_encstatus_json (int status) printf ("}]"); } +#ifdef GMIME_ATLEAST_26 +static void +format_part_sigstatus_json (GMimeSignatureList *siglist) +{ + printf (", \"sigstatus\": ["); + + if (!siglist) { + printf ("]"); + return; + } + + void *ctx_quote = talloc_new (NULL); + int i; + for (i = 0; i < g_mime_signature_list_length (siglist); i++) { + GMimeSignature *signature = g_mime_signature_list_get_signature (siglist, i); + + if (i > 0) + printf (", "); + + printf ("{"); + + /* status */ + GMimeSignatureStatus status = g_mime_signature_get_status (signature); + printf ("\"status\": %s", + json_quote_str (ctx_quote, + signature_status_to_string (status))); + + GMimeCertificate *certificate = g_mime_signature_get_certificate (signature); + if (status == GMIME_SIGNATURE_STATUS_GOOD) { + if (certificate) + printf (", \"fingerprint\": %s", json_quote_str (ctx_quote, g_mime_certificate_get_fingerprint (certificate))); + /* these dates are seconds since the epoch; should we + * provide a more human-readable format string? */ + time_t created = g_mime_signature_get_created (signature); + if (created != -1) + printf (", \"created\": %d", (int) created); + time_t expires = g_mime_signature_get_expires (signature); + if (expires > 0) + printf (", \"expires\": %d", (int) expires); + /* output user id only if validity is FULL or ULTIMATE. */ + /* note that gmime is using the term "trust" here, which + * is WRONG. It's actually user id "validity". */ + if (certificate) { + const char *name = g_mime_certificate_get_name (certificate); + GMimeCertificateTrust trust = g_mime_certificate_get_trust (certificate); + if (name && (trust == GMIME_CERTIFICATE_TRUST_FULLY || trust == GMIME_CERTIFICATE_TRUST_ULTIMATE)) + printf (", \"userid\": %s", json_quote_str (ctx_quote, name)); + } + } else if (certificate) { + const char *key_id = g_mime_certificate_get_key_id (certificate); + if (key_id) + printf (", \"keyid\": %s", json_quote_str (ctx_quote, key_id)); + } + + GMimeSignatureError errors = g_mime_signature_get_errors (signature); + if (errors != GMIME_SIGNATURE_ERROR_NONE) { + printf (", \"errors\": %d", errors); + } + + printf ("}"); + } + + printf ("]"); + + talloc_free (ctx_quote); +} +#else static void format_part_sigstatus_json (const GMimeSignatureValidity* validity) { @@ -652,6 +739,7 @@ format_part_sigstatus_json (const GMimeSignatureValidity* validity) talloc_free (ctx_quote); } +#endif static void format_part_content_json (GMimeObject *part) @@ -1000,13 +1088,20 @@ notmuch_show_command (void *ctx, unused (int argc), unused (char *argv[])) } else if ((STRNCMP_LITERAL (argv[i], "--verify") == 0) || (STRNCMP_LITERAL (argv[i], "--decrypt") == 0)) { if (params.cryptoctx == NULL) { +#ifdef GMIME_ATLEAST_26 + /* TODO: GMimePasswordRequestFunc */ + if (NULL == (params.cryptoctx = g_mime_gpg_context_new(NULL, "gpg"))) +#else GMimeSession* session = g_object_new(g_mime_session_get_type(), NULL); if (NULL == (params.cryptoctx = g_mime_gpg_context_new(session, "gpg"))) +#endif fprintf (stderr, "Failed to construct gpg context.\n"); else g_mime_gpg_context_set_always_trust((GMimeGpgContext*)params.cryptoctx, FALSE); +#ifndef GMIME_ATLEAST_26 g_object_unref (session); session = NULL; +#endif } if (STRNCMP_LITERAL (argv[i], "--decrypt") == 0) params.decrypt = 1; diff --git a/show-message.c b/show-message.c index 8768889..83ecf81 100644 --- a/show-message.c +++ b/show-message.c @@ -48,7 +48,11 @@ show_message_part (mime_node_t *node, format->part_encstatus (node->decrypt_success); if (node->verify_attempted && format->part_sigstatus) +#ifdef GMIME_ATLEAST_26 + format->part_sigstatus (node->sig_list); +#else format->part_sigstatus (node->sig_validity); +#endif format->part_content (part); diff --git a/test/crypto b/test/crypto index 0af4aa8..446a58b 100755 --- a/test/crypto +++ b/test/crypto @@ -104,6 +104,8 @@ test_expect_equal \ "$expected" test_begin_subtest "signature verification with signer key unavailable" +# this is broken with current versions of gmime-2.6 +(ldd $(which notmuch) | grep -Fq gmime-2.6) && test_subtest_known_broken # move the gnupghome temporarily out of the way mv "${GNUPGHOME}"{,.bak} output=$(notmuch show --format=json --verify subject:"test signed message 001" \ -- cgit v1.2.3 From da9f39216555934327a91ebc6b3b726b0a989dcf Mon Sep 17 00:00:00 2001 From: Tomi Ollila Date: Wed, 11 Jan 2012 18:53:59 +0200 Subject: test: whitespace-cleanup for most test/* files Used emacs (whitespace-cleanup) function to "cleanup blank problems" in test files where that could be done without breaking tests; test/emacs was partially, and test/multipart was fully reverted. --- test/emacs | 50 ++++++++-------- test/encoding | 2 +- test/from-guessing | 126 +++++++++++++++++++-------------------- test/reply | 58 +++++++++--------- test/search-position-overlap-bug | 4 +- test/symbol-hiding | 2 +- test/test-lib.sh | 10 ++-- test/thread-naming | 30 +++++----- 8 files changed, 141 insertions(+), 141 deletions(-) (limited to 'test') diff --git a/test/emacs b/test/emacs index ac47b16..f150d95 100755 --- a/test/emacs +++ b/test/emacs @@ -225,7 +225,7 @@ test_expect_equal_file OUTPUT EXPECTED 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\") @@ -373,22 +373,22 @@ add_message '[date]="Sat, 01 Jan 2000 12:00:00 -0000"' \ '[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) - (switch-to-buffer - (generate-new-buffer "*test-stashing*")) - (dotimes (i 9) - (yank) - (insert "\n") - (rotate-yank-pointer 1)) - (reverse-region (point-min) (point-max)) + (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) + (switch-to-buffer + (generate-new-buffer "*test-stashing*")) + (dotimes (i 9) + (yank) + (insert "\n") + (rotate-yank-pointer 1)) + (reverse-region (point-min) (point-max)) (test-output)' cat <EXPECTED Sat, 01 Jan 2000 12:00:00 -0000 @@ -405,11 +405,11 @@ 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) + (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" @@ -438,9 +438,9 @@ test_expect_equal_file OUTPUT EXPECTED test_begin_subtest "Refresh modified show buffer" test_subtest_known_broken test_emacs '(notmuch-show "id:f35dbb950911171438k5df6eb56k77b6c0944e2e79ae@mail.gmail.com") - (notmuch-show-toggle-message) - (notmuch-show-next-message) - (notmuch-show-toggle-message) + (notmuch-show-toggle-message) + (notmuch-show-next-message) + (notmuch-show-toggle-message) (test-visible-output "EXPECTED") (notmuch-show-refresh-view) (test-visible-output)' diff --git a/test/encoding b/test/encoding index e875c8b..33259c1 100755 --- a/test/encoding +++ b/test/encoding @@ -4,7 +4,7 @@ test_description="encoding issues" test_begin_subtest "Message with text of unknown charset" add_message '[content-type]="text/plain; charset=unknown-8bit"' \ - "[body]=irrelevant" + "[body]=irrelevant" output=$(notmuch show id:${gen_msg_id} 2>&1 | notmuch_show_sanitize) test_expect_equal "$output" " message{ id:msg-001@notmuch-test-suite depth:0 match:1 filename:/XXX/mail/msg-001 header{ diff --git a/test/from-guessing b/test/from-guessing index 8b69cf6..6dfaa40 100755 --- a/test/from-guessing +++ b/test/from-guessing @@ -4,10 +4,10 @@ test_description="From line heuristics (with multiple configured addresses)" test_begin_subtest "Magic from guessing (nothing to go on)" add_message '[from]="Sender "' \ - [to]=mailinglist@notmuchmail.org \ - [subject]=notmuch-reply-test \ - '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \ - '[body]="from guessing test"' + [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 @@ -21,11 +21,11 @@ On Tue, 05 Jan 2010 15:43:56 -0000, Sender wrote: test_begin_subtest "Magic from guessing (Envelope-to:)" add_message '[from]="Sender "' \ - [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"' + [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 @@ -39,11 +39,11 @@ On Tue, 05 Jan 2010 15:43:56 -0000, Sender wrote: test_begin_subtest "Magic from guessing (X-Original-To:)" add_message '[from]="Sender "' \ - [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"' + [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 @@ -57,13 +57,13 @@ On Tue, 05 Jan 2010 15:43:56 -0000, Sender wrote: test_begin_subtest "Magic from guessing (Received: .. for ..)" add_message '[from]="Sender "' \ - [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 ; Sat, 10 Apr 2010 07:54:51 -0400 (EDT)\"" \ - '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \ - '[body]="from guessing test"' + [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 ; 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 @@ -77,13 +77,13 @@ On Tue, 05 Jan 2010 15:43:56 -0000, Sender wrote: test_begin_subtest "Magic from guessing (Received: domain)" add_message '[from]="Sender "' \ - [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"' + [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 @@ -97,15 +97,15 @@ On Tue, 05 Jan 2010 15:43:56 -0000, Sender wrote: test_begin_subtest "Magic from guessing (multiple Received: headers)" add_message '[from]="Sender "' \ - [to]=mailinglist@notmuchmail.org \ - [subject]=notmuch-reply-test \ - "[header]=\"Received: from extraneous.example.com (extraneous.example.com [1.1.1.1]) + [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 ; Sat, 10 Apr 2010 07:54:51 -0400 (EDT) + by mail.otherdomain.org (some MTA) with ESMTP id 12345678 + for ; 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"' + '[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 @@ -123,10 +123,10 @@ test_expect_equal '' '' test_begin_subtest "Magic from guessing (nothing to go on)" add_message '[from]="Sender "' \ - [to]=mailinglist@notmuchmail.org \ - [subject]=notmuch-reply-test \ - '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \ - '[body]="from guessing test"' + [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 @@ -140,11 +140,11 @@ On Tue, 05 Jan 2010 15:43:56 -0000, Sender wrote: test_begin_subtest "Magic from guessing (Envelope-to:)" add_message '[from]="Sender "' \ - [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"' + [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 @@ -158,11 +158,11 @@ On Tue, 05 Jan 2010 15:43:56 -0000, Sender wrote: test_begin_subtest "Magic from guessing (X-Original-To:)" add_message '[from]="Sender "' \ - [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"' + [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 @@ -176,13 +176,13 @@ On Tue, 05 Jan 2010 15:43:56 -0000, Sender wrote: test_begin_subtest "Magic from guessing (Received: .. for ..)" add_message '[from]="Sender "' \ - [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 ; Sat, 10 Apr 2010 07:54:51 -0400 (EDT)\"" \ - '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \ - '[body]="from guessing test"' + [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 ; 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 @@ -196,13 +196,13 @@ On Tue, 05 Jan 2010 15:43:56 -0000, Sender wrote: test_begin_subtest "Magic from guessing (Received: domain)" add_message '[from]="Sender "' \ - [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"' + [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 diff --git a/test/reply b/test/reply index e4e16eb..00f4bea 100755 --- a/test/reply +++ b/test/reply @@ -4,10 +4,10 @@ test_description="\"notmuch reply\" in several variations" test_begin_subtest "Basic reply" add_message '[from]="Sender "' \ - [to]=test_suite@notmuchmail.org \ - [subject]=notmuch-reply-test \ - '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \ - '[body]="basic reply test"' + [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 @@ -21,10 +21,10 @@ On Tue, 05 Jan 2010 15:43:56 -0000, Sender wrote: test_begin_subtest "Multiple recipients" add_message '[from]="Sender "' \ - '[to]="test_suite@notmuchmail.org, Someone Else "' \ - [subject]=notmuch-reply-test \ - '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \ - '[body]="Multiple recipients"' + '[to]="test_suite@notmuchmail.org, Someone Else "' \ + [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 @@ -38,11 +38,11 @@ On Tue, 05 Jan 2010 15:43:56 -0000, Sender wrote: test_begin_subtest "Reply with CC" add_message '[from]="Sender "' \ - [to]=test_suite@notmuchmail.org \ - '[cc]="Other Parties "' \ - [subject]=notmuch-reply-test \ - '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \ - '[body]="reply with CC"' + [to]=test_suite@notmuchmail.org \ + '[cc]="Other Parties "' \ + [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 @@ -57,10 +57,10 @@ On Tue, 05 Jan 2010 15:43:56 -0000, Sender wrote: test_begin_subtest "Reply from alternate address" add_message '[from]="Sender "' \ - [to]=test_suite_other@notmuchmail.org \ - [subject]=notmuch-reply-test \ - '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \ - '[body]="reply from alternate address"' + [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 @@ -92,11 +92,11 @@ On Tue, 05 Jan 2010 15:43:56 -0000, Sender wrote: test_begin_subtest "Support for Reply-To" add_message '[from]="Sender "' \ - [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 "' + [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 "' output=$(notmuch reply id:${gen_msg_id}) test_expect_equal "$output" "From: Notmuch Test Suite @@ -110,11 +110,11 @@ On Tue, 05 Jan 2010 15:43:56 -0000, Sender wrote: test_begin_subtest "Un-munging Reply-To" add_message '[from]="Sender "' \ - '[to]="Some List "' \ - [subject]=notmuch-reply-test \ - '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \ - '[body]="Un-munging Reply-To"' \ - '[reply-to]="Evil Munging List "' + '[to]="Some List "' \ + [subject]=notmuch-reply-test \ + '[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \ + '[body]="Un-munging Reply-To"' \ + '[reply-to]="Evil Munging List "' output=$(notmuch reply id:${gen_msg_id}) test_expect_equal "$output" "From: Notmuch Test Suite @@ -128,8 +128,8 @@ On Tue, 05 Jan 2010 15:43:56 -0000, Sender wrote: 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"' + '[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 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 diff --git a/test/search-position-overlap-bug b/test/search-position-overlap-bug index 414b8d5..5da6ad6 100755 --- a/test/search-position-overlap-bug +++ b/test/search-position-overlap-bug @@ -1,7 +1,7 @@ #!/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 @@ -12,7 +12,7 @@ # 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 diff --git a/test/symbol-hiding b/test/symbol-hiding index 7fa7b2a..636ec91 100755 --- a/test/symbol-hiding +++ b/test/symbol-hiding @@ -23,7 +23,7 @@ mkdir -p fakedb/.notmuch test_expect_success 'running test' run_test test_begin_subtest 'checking output' -test_expect_equal "$result" "$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 diff --git a/test/test-lib.sh b/test/test-lib.sh index d1fbc05..0da60fb 100644 --- a/test/test-lib.sh +++ b/test/test-lib.sh @@ -140,7 +140,7 @@ if test -n "$color"; then esac shift printf " " - printf "$@" + printf "$@" tput sgr0 print_subtest ) @@ -150,7 +150,7 @@ else test -z "$1" && test -n "$quiet" && return shift printf " " - printf "$@" + printf "$@" print_subtest } fi @@ -249,7 +249,7 @@ remove_cr () { # Store the message in file 'name'. The default is to store it # in 'msg-', where is three-digit number of the # message. -# +# # [body]=text # # Text to use as the body of the email message @@ -869,7 +869,7 @@ test_done () { [ -n "$EMACS_SERVER" ] && test_emacs '(kill-emacs)' if [ "$test_failure" = "0" ]; then - if [ "$test_broken" = "0" ]; then + if [ "$test_broken" = "0" ]; then rm -rf "$remove_tmp" fi exit 0 @@ -881,7 +881,7 @@ test_done () { emacs_generate_script () { # Construct a little test script here for the benefit of the user, # (who can easily run "run_emacs" to get the same emacs environment - # for investigating any failures). + # for investigating any failures). cat <"$TMP_DIRECTORY/run_emacs" #!/bin/sh export PATH=$PATH diff --git a/test/thread-naming b/test/thread-naming index 41b97d9..2ce9216 100755 --- a/test/thread-naming +++ b/test/thread-naming @@ -4,18 +4,18 @@ test_description="naming of threads with changing subject" 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"' + '[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\>" + '[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\>" + '[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\>" + '[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)" @@ -37,29 +37,29 @@ test_expect_equal "$output" "thread:XXX 2001-01-07 [2/4] Notmuch Test Suite; t 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\>" + '[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\>" + '[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\>" + '[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\>" + '[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)" -- cgit v1.2.3 From a04642043fa8f071e0dbc73a204fcc91dc3c8401 Mon Sep 17 00:00:00 2001 From: Tomi Ollila Date: Fri, 13 Jan 2012 10:17:28 +0200 Subject: test: make (kill-emacs) from emacsclient work with emacs 23.(1|2) emacsclient --eval '(kill-emacs)' makes emacs versions 23.1 and 23.2 ask user input from running emacs. Redefining yes-or-no-p function when kill-emacs is executed for these emacs versions in test-lib.el avoids this test problem. --- test/test-lib.el | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'test') diff --git a/test/test-lib.el b/test/test-lib.el index 3b817c3..59c5868 100644 --- a/test/test-lib.el +++ b/test/test-lib.el @@ -26,6 +26,13 @@ ;; `read' call. (setq read-file-name-function (lambda (&rest _) (read))) +;; Work around a bug in emacs 23.1 and emacs 23.2 which prevents +;; noninteractive (kill-emacs) from emacsclient. +(if (and (= emacs-major-version 23) (< emacs-minor-version 3)) + (defadvice kill-emacs (before disable-yes-or-no-p activate) + "Disable yes-or-no-p before executing kill-emacs" + (defun yes-or-no-p (prompt) t))) + (defun notmuch-test-wait () "Wait for process completion." (while (get-buffer-process (current-buffer)) -- cgit v1.2.3 From 80771e3c76573613b18b700983e0d29fea5630a3 Mon Sep 17 00:00:00 2001 From: Pieter Praet Date: Mon, 23 Jan 2012 05:26:10 +0100 Subject: test/emacs-large-search-buffer: correct typo (EXPEXTED -> EXPECTED) introduced in commit 3b24b396 --- test/emacs-large-search-buffer | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'test') diff --git a/test/emacs-large-search-buffer b/test/emacs-large-search-buffer index 6095e9d..4351e33 100755 --- a/test/emacs-large-search-buffer +++ b/test/emacs-large-search-buffer @@ -19,25 +19,25 @@ done notmuch new > /dev/null test_begin_subtest "Ensure that emacs doesn't drop results" -notmuch search '*' > EXPEXTED -sed -i -e 's/^thread:[0-9a-f]* //' -e 's/;//' -e 's/xx*/[BLOB]/' EXPEXTED -echo 'End of search results.' >> EXPEXTED +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 EXPEXTED +test_expect_equal_file OUTPUT EXPECTED test_begin_subtest "Ensure that emacs doesn't drop error messages" test_emacs '(notmuch-search "--this-option-does-not-exist") (notmuch-test-wait) (test-output)' -cat <EXPEXTED +cat <EXPECTED Error: Unexpected output from notmuch search: Unrecognized option: --this-option-does-not-exist End of search results. (process returned 1) EOF -test_expect_equal_file OUTPUT EXPEXTED +test_expect_equal_file OUTPUT EXPECTED test_done -- cgit v1.2.3 From 0bd09f844677ba361318d129bd01e21b0f7c1bd9 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Sun, 22 Jan 2012 21:31:12 -0500 Subject: show: Use consistent header ordering in the text format Previously, top-level message headers were printed as Subject, From, To, Date, while embedded message headers were printed From, To, Subject, Date. This makes both cases use the former order and updates the tests accordingly. Strangely, the raw format also uses this function, so this also fixes the two raw format tests affected by this change. --- notmuch-show.c | 2 +- test/multipart | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'test') diff --git a/notmuch-show.c b/notmuch-show.c index 7b40568..682aa71 100644 --- a/notmuch-show.c +++ b/notmuch-show.c @@ -364,6 +364,7 @@ format_headers_message_part_text (GMimeMessage *message) InternetAddressList *recipients; const char *recipients_string; + printf ("Subject: %s\n", g_mime_message_get_subject (message)); printf ("From: %s\n", g_mime_message_get_sender (message)); recipients = g_mime_message_get_recipients (message, GMIME_RECIPIENT_TYPE_TO); recipients_string = internet_address_list_to_string (recipients, 0); @@ -375,7 +376,6 @@ format_headers_message_part_text (GMimeMessage *message) if (recipients_string) printf ("Cc: %s\n", recipients_string); - printf ("Subject: %s\n", g_mime_message_get_subject (message)); printf ("Date: %s\n", g_mime_message_get_date_as_string (message)); } diff --git a/test/multipart b/test/multipart index f83526b..2dd73f5 100755 --- a/test/multipart +++ b/test/multipart @@ -121,9 +121,9 @@ Date: Fri, 05 Jan 2001 15:43:57 +0000 part{ ID: 2, Content-type: multipart/mixed part{ ID: 3, Content-type: message/rfc822 header{ +Subject: html message From: Carl Worth To: cworth@cworth.org -Subject: html message Date: Fri, 05 Jan 2001 15:42:57 +0000 header} body{ @@ -162,9 +162,9 @@ cat <EXPECTED part{ ID: 2, Content-type: multipart/mixed part{ ID: 3, Content-type: message/rfc822 header{ +Subject: html message From: Carl Worth To: cworth@cworth.org -Subject: html message Date: Fri, 05 Jan 2001 15:42:57 +0000 header} body{ @@ -200,9 +200,9 @@ cat <EXPECTED part{ ID: 2, Content-type: multipart/mixed part{ ID: 3, Content-type: message/rfc822 header{ +Subject: html message From: Carl Worth To: cworth@cworth.org -Subject: html message Date: Fri, 05 Jan 2001 15:42:57 +0000 header} body{ @@ -233,9 +233,9 @@ notmuch show --format=text --part=3 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OU cat <EXPECTED part{ ID: 3, Content-type: message/rfc822 header{ +Subject: html message From: Carl Worth To: cworth@cworth.org -Subject: html message Date: Fri, 05 Jan 2001 15:42:57 +0000 header} body{ @@ -452,9 +452,9 @@ notmuch show --format=raw --part=1 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUT # output should *not* include newline echo >>OUTPUT cat <EXPECTED +Subject: html message From: Carl Worth To: cworth@cworth.org -Subject: html message Date: Fri, 05 Jan 2001 15:42:57 +0000

This is an embedded message, with a multipart/alternative part.

@@ -476,9 +476,9 @@ test_expect_equal_file OUTPUT EXPECTED test_begin_subtest "--format=raw --part=2, multipart/mixed" notmuch show --format=raw --part=2 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT cat <EXPECTED +Subject: html message From: Carl Worth To: cworth@cworth.org -Subject: html message Date: Fri, 05 Jan 2001 15:42:57 +0000

This is an embedded message, with a multipart/alternative part.

-- cgit v1.2.3 From 6795c62a50815786fd168536371cf6b9ed817535 Mon Sep 17 00:00:00 2001 From: Pieter Praet Date: Mon, 23 Jan 2012 05:22:33 +0100 Subject: test: only exclude "deleted" messages from search if explicitly configured Currently, the 'search.exclude_tags' option is automatically set to "deleted;spam;" if it's missing from the config file. This violates the Principle of Least Surprise, so update the tests to *only* expect the exclusion of messages which are tagged "deleted" if the 'search.exclude_tags' option is explicitly set *and* contains that tag. --- test/search | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'test') diff --git a/test/search b/test/search index bf965e7..99d94bd 100755 --- a/test/search +++ b/test/search @@ -130,6 +130,7 @@ 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_begin_subtest "Exclude \"deleted\" messages from search" +notmuch config set search.exclude_tags = deleted generate_message '[subject]="Not deleted"' generate_message '[subject]="Deleted"' notmuch new > /dev/null @@ -147,4 +148,11 @@ 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 "Don't exclude \"deleted\" messages from search if not configured" +test_subtest_known_broken +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)" + test_done -- cgit v1.2.3 From ba33a15ec3ab80b175cf54d2584aa8acd1a2dc6e Mon Sep 17 00:00:00 2001 From: Pieter Praet Date: Mon, 23 Jan 2012 05:22:34 +0100 Subject: config: only exclude messages if 'search.exclude_tags' is explicitly set Currently, the 'search.exclude_tags' option is automatically set to "deleted;spam;" if it's missing from the config file. This violates the Principle of Least Surprise, so *only* set 'search.exclude_tags' to "deleted;spam;" if we didn't find a configuration file at all. This patch is actually Austin Clements' work: id:"20120117203211.GQ16740@mit.edu" --- notmuch-config.c | 8 ++++++-- test/search | 1 - 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'test') diff --git a/notmuch-config.c b/notmuch-config.c index 39da888..0ded6d7 100644 --- a/notmuch-config.c +++ b/notmuch-config.c @@ -362,8 +362,12 @@ notmuch_config_open (void *ctx, } if (notmuch_config_get_search_exclude_tags (config, &tmp) == NULL) { - const char *tags[] = { "deleted", "spam" }; - notmuch_config_set_search_exclude_tags (config, tags, 2); + if (is_new) { + const char *tags[] = { "deleted", "spam" }; + notmuch_config_set_search_exclude_tags (config, tags, 2); + } else { + notmuch_config_set_search_exclude_tags (config, NULL, 0); + } } error = NULL; diff --git a/test/search b/test/search index 99d94bd..414be35 100755 --- a/test/search +++ b/test/search @@ -149,7 +149,6 @@ test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; N thread:XXX 2001-01-05 [1/2] Notmuch Test Suite; Not deleted reply (deleted inbox unread)" test_begin_subtest "Don't exclude \"deleted\" messages from search if not configured" -test_subtest_known_broken 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) -- cgit v1.2.3 From 2903b32f79dcf7789a2b015c48194cb40ac71462 Mon Sep 17 00:00:00 2001 From: David Edmondson Date: Tue, 24 Jan 2012 16:14:04 +0000 Subject: test: Don't return the result of checking for running emacs to the tester. When checking for a running emacs, test_emacs evaluates the empty list '()'. This returns 'nil' when emacs is running, which is then prepended to the actual test result. Given that it is not part of the actual test output the test harness can incorrectly report test failure (or success). --- test/test-lib.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'test') diff --git a/test/test-lib.sh b/test/test-lib.sh index 0da60fb..82c686c 100644 --- a/test/test-lib.sh +++ b/test/test-lib.sh @@ -926,7 +926,7 @@ test_emacs () { --eval '(orphan-watchdog $$)'" || return EMACS_SERVER="$server_name" # wait until the emacs server is up - until test_emacs '()' 2>/dev/null; do + until test_emacs '()' >/dev/null 2>/dev/null; do sleep 1 done fi -- cgit v1.2.3 From 260975e8aff635b6b99db835ee8d40ec33ee916c Mon Sep 17 00:00:00 2001 From: David Edmondson Date: Tue, 24 Jan 2012 16:14:05 +0000 Subject: test: Add `test_emacs_expect_t'. Add a new test function to allow simpler testing of emacs functionality. `test_emacs_expect_t' takes one argument - a lisp expression to evaluate. The test passes if the expression returns `t', otherwise it fails and the output is reported to the tester. --- test/README | 8 ++++++++ test/emacs-test-functions.sh | 9 +++++++++ test/notmuch-test | 1 + test/test-lib.el | 9 +++++++++ test/test-lib.sh | 29 +++++++++++++++++++++++++++++ 5 files changed, 56 insertions(+) create mode 100755 test/emacs-test-functions.sh (limited to 'test') diff --git a/test/README b/test/README index 44ff653..43656a3 100644 --- a/test/README +++ b/test/README @@ -202,6 +202,14 @@ library for your script to use. tests that may run in the same Emacs instance. Use `let' instead so the scope of the changed variables is limited to a single test. + test_emacs_expect_t + + This function executes the provided emacs lisp script within + emacs in a manner similar to 'test_emacs'. The expressions should + return the value `t' to indicate that the test has passed. If the + test does not return `t' then it is considered failed and all data + returned by the test is reported to the tester. + test_done Your test script must have test_done at the end. Its purpose diff --git a/test/emacs-test-functions.sh b/test/emacs-test-functions.sh new file mode 100755 index 0000000..0e1f9fc --- /dev/null +++ b/test/emacs-test-functions.sh @@ -0,0 +1,9 @@ +#!/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 diff --git a/test/notmuch-test b/test/notmuch-test index 6a99ae3..d034f99 100755 --- a/test/notmuch-test +++ b/test/notmuch-test @@ -52,6 +52,7 @@ TESTS=" python hooks argument-parsing + emacs-test-functions.sh " TESTS=${NOTMUCH_TESTS:=$TESTS} diff --git a/test/test-lib.el b/test/test-lib.el index 59c5868..96752f0 100644 --- a/test/test-lib.el +++ b/test/test-lib.el @@ -83,3 +83,12 @@ nothing." (add-hook-counter 'notmuch-hello-mode-hook) (add-hook-counter 'notmuch-hello-refresh-hook) + +(defmacro notmuch-test-run (&rest body) + "Evaluate a BODY of test expressions and output the result." + `(with-temp-buffer + (let ((result (progn ,@body))) + (insert (if (stringp result) + result + (prin1-to-string result))) + (test-output)))) diff --git a/test/test-lib.sh b/test/test-lib.sh index 82c686c..8158328 100644 --- a/test/test-lib.sh +++ b/test/test-lib.sh @@ -503,6 +503,35 @@ test_expect_equal_file () fi } +test_emacs_expect_t () { + test "$#" = 2 && { prereq=$1; shift; } || prereq= + test "$#" = 1 || + error "bug in the test script: not 1 or 2 parameters to test_emacs_expect_t" + + # Run the test. + if ! test_skip "$test_subtest_name" + then + test_emacs "(notmuch-test-run $1)" >/dev/null + + # Restore state after the test. + exec 1>&6 2>&7 # Restore stdout and stderr + inside_subtest= + + # Report success/failure. + result=$(cat OUTPUT) + if [ "$result" = t ] + then + test_ok_ "$test_subtest_name" + else + test_failure_ "$test_subtest_name" "${result}" + fi + else + # Restore state after the (non) test. + exec 1>&6 2>&7 # Restore stdout and stderr + inside_subtest= + fi +} + NOTMUCH_NEW () { notmuch new | grep -v -E -e '^Processed [0-9]*( total)? file|Found [0-9]* total file' -- cgit v1.2.3 From f92d7dee8fcf399bda361df82187523598bb09b4 Mon Sep 17 00:00:00 2001 From: David Edmondson Date: Tue, 24 Jan 2012 16:14:06 +0000 Subject: test: Add more helpers for emacs tests. --- test/test-lib.el | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'test') diff --git a/test/test-lib.el b/test/test-lib.el index 96752f0..bc75f06 100644 --- a/test/test-lib.el +++ b/test/test-lib.el @@ -20,6 +20,8 @@ ;; ;; Authors: Dmitry Kurochkin +(require 'cl) ;; This code is generally used uncompiled. + ;; `read-file-name' by default uses `completing-read' function to read ;; user input. It does not respect `standard-input' variable which we ;; use in tests to provide user input. So replace it with a plain @@ -92,3 +94,27 @@ nothing." result (prin1-to-string result))) (test-output)))) + +(defun notmuch-test-report-unexpected (output expected) + "Report that the OUTPUT does not match the EXPECTED result." + (concat "Expect:\t" (prin1-to-string expected) "\n" + "Output:\t" (prin1-to-string output) "\n")) + +(defun notmuch-test-expect-equal (output expected) + "Compare OUTPUT with EXPECTED. Report any discrepencies." + (if (equal output expected) + t + (cond + ((and (listp output) + (listp expected)) + ;; Reporting the difference between two lists is done by + ;; reporting differing elements of OUTPUT and EXPECTED + ;; pairwise. This is expected to make analysis of failures + ;; simpler. + (apply #'concat (loop for o in output + for e in expected + if (not (equal o e)) + collect (notmuch-test-report-unexpected o e)))) + + (t + (notmuch-test-report-unexpected output expected))))) -- cgit v1.2.3 From 3699fedb3accf5fbd8085c0789d43c716d6ad3e9 Mon Sep 17 00:00:00 2001 From: David Edmondson Date: Tue, 24 Jan 2012 16:14:07 +0000 Subject: test: Add address cleaning tests. --- test/emacs-address-cleaning.el | 29 +++++++++++++++++++++++++++++ test/emacs-address-cleaning.sh | 19 +++++++++++++++++++ test/notmuch-test | 1 + 3 files changed, 49 insertions(+) create mode 100644 test/emacs-address-cleaning.el create mode 100755 test/emacs-address-cleaning.sh (limited to 'test') diff --git a/test/emacs-address-cleaning.el b/test/emacs-address-cleaning.el new file mode 100644 index 0000000..19e9e05 --- /dev/null +++ b/test/emacs-address-cleaning.el @@ -0,0 +1,29 @@ +(defun notmuch-test-address-cleaning-1 () + (notmuch-test-expect-equal (notmuch-show-clean-address "dme@dme.org") + "dme@dme.org")) + +(defun notmuch-test-address-cleaning-2 () + (let* ((input '("foo@bar.com" + "" + "Foo Bar " + "foo@bar.com " + "\"Foo Bar\" ")) + (expected '("foo@bar.com" + "foo@bar.com" + "Foo Bar " + "foo@bar.com" + "Foo Bar ")) + (output (mapcar #'notmuch-show-clean-address input))) + (notmuch-test-expect-equal output expected))) + +(defun notmuch-test-address-cleaning-3 () + (let* ((input '("ДБ " + "foo (at home) " + "foo [at home] " + "Foo Bar")) + (expected '("ДБ " + "foo (at home) " + "foo [at home] " + "Foo Bar")) + (output (mapcar #'notmuch-show-clean-address input))) + (notmuch-test-expect-equal output expected))) diff --git a/test/emacs-address-cleaning.sh b/test/emacs-address-cleaning.sh new file mode 100755 index 0000000..0d85bdc --- /dev/null +++ b/test/emacs-address-cleaning.sh @@ -0,0 +1,19 @@ +#!/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 \ + '(load "emacs-address-cleaning.el") (notmuch-test-address-cleaning-1)' + +test_begin_subtest "notmuch-test-address-clean part 2" +test_emacs_expect_t \ + '(load "emacs-address-cleaning.el") (notmuch-test-address-cleaning-2)' + +test_begin_subtest "notmuch-test-address-clean part 3" +test_subtest_known_broken +test_emacs_expect_t \ + '(load "emacs-address-cleaning.el") (notmuch-test-address-cleaning-3)' + +test_done diff --git a/test/notmuch-test b/test/notmuch-test index d034f99..3f1740c 100755 --- a/test/notmuch-test +++ b/test/notmuch-test @@ -53,6 +53,7 @@ TESTS=" hooks argument-parsing emacs-test-functions.sh + emacs-address-cleaning.sh " TESTS=${NOTMUCH_TESTS:=$TESTS} -- cgit v1.2.3 From 02d88159226b351091ae94e2176d2e59c79d21d3 Mon Sep 17 00:00:00 2001 From: Dmitry Kurochkin Date: Wed, 25 Jan 2012 05:10:52 +0400 Subject: emacs: bind "s" to `notmuch-search' in notmuch-hello buffer Before the change, "s" in notmuch-hello buffer would jump to the search box. The patch changes the binding to `notmuch-search' which is consistent with all other notmuch buffers. --- emacs/notmuch-hello.el | 19 ++++++------------- test/emacs.expected-output/notmuch-hello | 2 +- .../notmuch-hello-no-saved-searches | 2 +- test/emacs.expected-output/notmuch-hello-with-empty | 2 +- 4 files changed, 9 insertions(+), 16 deletions(-) (limited to 'test') diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el index 63f2e07..d88a870 100644 --- a/emacs/notmuch-hello.el +++ b/emacs/notmuch-hello.el @@ -29,9 +29,6 @@ (declare-function notmuch-search "notmuch" (query &optional oldest-first target-thread target-line continuation)) (declare-function notmuch-poll "notmuch" ()) -(defvar notmuch-hello-search-bar-marker nil - "The position of the search bar within the notmuch-hello buffer.") - (defcustom notmuch-recent-searches-max 10 "The number of recent searches to store and display." :type 'integer @@ -324,11 +321,6 @@ should be. Returns a cons cell `(tags-per-line width)'." (widget-insert "\n")) found-target-pos)) -(defun notmuch-hello-goto-search () - "Put point inside the `search' widget." - (interactive) - (goto-char notmuch-hello-search-bar-marker)) - (defimage notmuch-hello-logo ((:type png :file "notmuch-logo.png"))) (defun notmuch-hello-search-continuation() @@ -358,7 +350,7 @@ should be. Returns a cons cell `(tags-per-line width)'." (define-key map "G" 'notmuch-hello-poll-and-update) (define-key map (kbd "") 'widget-backward) (define-key map "m" 'notmuch-mua-new-mail) - (define-key map "s" 'notmuch-hello-goto-search) + (define-key map "s" 'notmuch-search) map) "Keymap for \"notmuch hello\" buffers.") (fset 'notmuch-hello-mode-map notmuch-hello-mode-map) @@ -471,7 +463,8 @@ Complete list of currently available key bindings: (widget-insert " messages.\n")) (let ((found-target-pos nil) - (final-target-pos nil)) + (final-target-pos nil) + (search-bar-pos)) (let* ((saved-alist ;; Filter out empty saved searches if required. (if notmuch-show-empty-saved-searches @@ -503,7 +496,7 @@ Complete list of currently available key bindings: (indent-rigidly start (point) notmuch-hello-indent))) (widget-insert "\nSearch: ") - (setq notmuch-hello-search-bar-marker (point-marker)) + (setq search-bar-pos (point-marker)) (widget-create 'editable-field ;; Leave some space at the start and end of the ;; search boxes. @@ -595,7 +588,7 @@ Complete list of currently available key bindings: (when notmuch-saved-searches (widget-insert "Edit saved searches with the `edit' button.\n")) (widget-insert "Hit RET or click on a saved search or tag name to view matching threads.\n") - (widget-insert "`=' refreshes this screen. `s' jumps to the search box. `q' to quit.\n") + (widget-insert "`=' refreshes this screen. `s' to search messages. `q' to quit.\n") (let ((fill-column (- (window-width) notmuch-hello-indent))) (center-region start (point)))) @@ -607,7 +600,7 @@ Complete list of currently available key bindings: (widget-forward 1))) (unless (widget-at) - (notmuch-hello-goto-search)))) + (goto-char search-bar-pos)))) (run-hooks 'notmuch-hello-refresh-hook)) diff --git a/test/emacs.expected-output/notmuch-hello b/test/emacs.expected-output/notmuch-hello index 196112e..c43ab8c 100644 --- a/test/emacs.expected-output/notmuch-hello +++ b/test/emacs.expected-output/notmuch-hello @@ -11,4 +11,4 @@ Search: . Type a search query and hit RET to view matching threads. Edit saved searches with the `edit' button. Hit RET or click on a saved search or tag name to view matching threads. - `=' refreshes this screen. `s' jumps to the search box. `q' to quit. + `=' refreshes this screen. `s' to search messages. `q' to quit. diff --git a/test/emacs.expected-output/notmuch-hello-no-saved-searches b/test/emacs.expected-output/notmuch-hello-no-saved-searches index f4cfe49..080a56b 100644 --- a/test/emacs.expected-output/notmuch-hello-no-saved-searches +++ b/test/emacs.expected-output/notmuch-hello-no-saved-searches @@ -7,4 +7,4 @@ Search: . Type a search query and hit RET to view matching threads. Edit saved searches with the `edit' button. Hit RET or click on a saved search or tag name to view matching threads. - `=' refreshes this screen. `s' jumps to the search box. `q' to quit. + `=' refreshes this screen. `s' to search messages. `q' to quit. diff --git a/test/emacs.expected-output/notmuch-hello-with-empty b/test/emacs.expected-output/notmuch-hello-with-empty index a860a72..a9e312c 100644 --- a/test/emacs.expected-output/notmuch-hello-with-empty +++ b/test/emacs.expected-output/notmuch-hello-with-empty @@ -11,4 +11,4 @@ Search: . Type a search query and hit RET to view matching threads. Edit saved searches with the `edit' button. Hit RET or click on a saved search or tag name to view matching threads. - `=' refreshes this screen. `s' jumps to the search box. `q' to quit. + `=' refreshes this screen. `s' to search messages. `q' to quit. -- cgit v1.2.3 From d0a048f8561f63de5e30cb23dec6b6facb79c851 Mon Sep 17 00:00:00 2001 From: Dmitry Kurochkin Date: Wed, 25 Jan 2012 22:24:56 +0400 Subject: emacs: polish notmuch-hello help text Make `=' binding description consistent with others. --- emacs/notmuch-hello.el | 2 +- test/emacs.expected-output/notmuch-hello | 2 +- test/emacs.expected-output/notmuch-hello-no-saved-searches | 2 +- test/emacs.expected-output/notmuch-hello-with-empty | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'test') diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el index ab65e36..d17a30f 100644 --- a/emacs/notmuch-hello.el +++ b/emacs/notmuch-hello.el @@ -580,7 +580,7 @@ Complete list of currently available key bindings: (when notmuch-saved-searches (widget-insert "Edit saved searches with the `edit' button.\n")) (widget-insert "Hit RET or click on a saved search or tag name to view matching threads.\n") - (widget-insert "`=' refreshes this screen. `s' to search messages. `q' to quit.\n") + (widget-insert "`=' to refresh this screen. `s' to search messages. `q' to quit.\n") (let ((fill-column (- (window-width) notmuch-hello-indent))) (center-region start (point)))) diff --git a/test/emacs.expected-output/notmuch-hello b/test/emacs.expected-output/notmuch-hello index c43ab8c..3e59595 100644 --- a/test/emacs.expected-output/notmuch-hello +++ b/test/emacs.expected-output/notmuch-hello @@ -11,4 +11,4 @@ Search: . Type a search query and hit RET to view matching threads. Edit saved searches with the `edit' button. Hit RET or click on a saved search or tag name to view matching threads. - `=' refreshes this screen. `s' to search messages. `q' to quit. + `=' to refresh this screen. `s' to search messages. `q' to quit. diff --git a/test/emacs.expected-output/notmuch-hello-no-saved-searches b/test/emacs.expected-output/notmuch-hello-no-saved-searches index 080a56b..ef0e5d0 100644 --- a/test/emacs.expected-output/notmuch-hello-no-saved-searches +++ b/test/emacs.expected-output/notmuch-hello-no-saved-searches @@ -7,4 +7,4 @@ Search: . Type a search query and hit RET to view matching threads. Edit saved searches with the `edit' button. Hit RET or click on a saved search or tag name to view matching threads. - `=' refreshes this screen. `s' to search messages. `q' to quit. + `=' to refresh this screen. `s' to search messages. `q' to quit. diff --git a/test/emacs.expected-output/notmuch-hello-with-empty b/test/emacs.expected-output/notmuch-hello-with-empty index a9e312c..71edba7 100644 --- a/test/emacs.expected-output/notmuch-hello-with-empty +++ b/test/emacs.expected-output/notmuch-hello-with-empty @@ -11,4 +11,4 @@ Search: . Type a search query and hit RET to view matching threads. Edit saved searches with the `edit' button. Hit RET or click on a saved search or tag name to view matching threads. - `=' refreshes this screen. `s' to search messages. `q' to quit. + `=' to refresh this screen. `s' to search messages. `q' to quit. -- cgit v1.2.3 From c70c7f86b83601231bac94db8a6596a1d729ae24 Mon Sep 17 00:00:00 2001 From: David Edmondson Date: Thu, 26 Jan 2012 07:19:37 +0000 Subject: test: `visible-buffer-substring' should not return text properties. When using `visible-buffer-substring' to examine a buffer, the text properties are not useful, so don't include them. --- test/test-lib.el | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'test') diff --git a/test/test-lib.el b/test/test-lib.el index bc75f06..5b32e0a 100644 --- a/test/test-lib.el +++ b/test/test-lib.el @@ -51,16 +51,19 @@ FILENAME is OUTPUT." (with-temp-file (or filename "OUTPUT") (insert text)))) (defun visible-buffer-string () - "Same as `buffer-string', but excludes invisible text." + "Same as `buffer-string', but excludes invisible text and +removes any text properties." (visible-buffer-substring (point-min) (point-max))) (defun visible-buffer-substring (start end) - "Same as `buffer-substring', but excludes invisible text." + "Same as `buffer-substring-no-properties', but excludes +invisible text." (let (str) (while (< start end) (let ((next-pos (next-char-property-change start end))) (when (not (invisible-p start)) - (setq str (concat str (buffer-substring start next-pos)))) + (setq str (concat str (buffer-substring-no-properties + start next-pos)))) (setq start next-pos))) str)) -- cgit v1.2.3 From 2f50524e27db2ca58f6543a2c73a5719d8d7f491 Mon Sep 17 00:00:00 2001 From: David Edmondson Date: Thu, 26 Jan 2012 07:19:38 +0000 Subject: test: `notmuch-test-run' should protect against buffer switching. The body of the test may cause the current buffer to change. Ensure that the output goes to the correct buffer by switching back before inserting it. --- test/test-lib.el | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'test') diff --git a/test/test-lib.el b/test/test-lib.el index 5b32e0a..6271da2 100644 --- a/test/test-lib.el +++ b/test/test-lib.el @@ -92,7 +92,9 @@ nothing." (defmacro notmuch-test-run (&rest body) "Evaluate a BODY of test expressions and output the result." `(with-temp-buffer - (let ((result (progn ,@body))) + (let ((buffer (current-buffer)) + (result (progn ,@body))) + (switch-to-buffer buffer) (insert (if (stringp result) result (prin1-to-string result))) -- cgit v1.2.3 From cbc4876a33d34be8cb6abad9303c366a6be142a8 Mon Sep 17 00:00:00 2001 From: David Edmondson Date: Wed, 25 Jan 2012 13:53:58 +0000 Subject: emacs: Avoid `mail-header-parse-address' in `notmuch-show-clean-address'. `mail-header-parse-address' expects un-decoded mailbox parts, which is not what we have at this point. Replace it with simple string deconstruction. Mark the corresponding test as no longer broken. Minor whitespace cleanup. --- emacs/notmuch-show.el | 50 ++++++++++++++++++++++++++++++------------ test/emacs-address-cleaning.sh | 1 - 2 files changed, 36 insertions(+), 15 deletions(-) (limited to 'test') diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index 94d94ed..acc2f5e 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -294,21 +294,43 @@ operation on the contents of the current buffer." "Try to clean a single email ADDRESS for display. Return unchanged ADDRESS if parsing fails." (condition-case nil - (let* ((parsed (mail-header-parse-address address)) - (address (car parsed)) - (name (cdr parsed))) - ;; Remove double quotes. They might be required during transport, - ;; but we don't need to see them. - (when name - (setq name (replace-regexp-in-string "\"" "" name))) + (let (p-name p-address) + ;; It would be convenient to use `mail-header-parse-address', + ;; but that expects un-decoded mailbox parts, whereas our + ;; mailbox parts are already decoded (and hence may contain + ;; UTF-8). Given that notmuch should handle most of the awkward + ;; cases, some simple string deconstruction should be sufficient + ;; here. + (cond + ;; "User " style. + ((string-match "\\(.*\\) <\\(.*\\)>" address) + (setq p-name (match-string 1 address) + p-address (match-string 2 address))) + + ;; "" style. + ((string-match "<\\(.*\\)>" address) + (setq p-address (match-string 1 address))) + + ;; Everything else. + (t + (setq p-address address))) + + ;; Remove outer double quotes. They might be required during + ;; transport, but we don't need to see them. + (when (and p-name + (string-match "^\"\\(.*\\)\"$" p-name)) + (setq p-name (match-string 1 p-name))) + ;; If the address is 'foo@bar.com ' then show just ;; 'foo@bar.com'. - (when (string= name address) - (setq name nil)) - - (if (not name) - address - (concat name " <" address ">"))) + (when (string= p-name p-address) + (setq p-name nil)) + + ;; If no name results, return just the address. + (if (not p-name) + p-address + ;; Otherwise format the name and address together. + (concat p-name " <" p-address ">"))) (error address))) (defun notmuch-show-insert-headerline (headers date tags depth) @@ -1423,7 +1445,7 @@ than only the current message." (interactive "P\nsPipe message to command: ") (let (shell-command) (if entire-thread - (setq shell-command + (setq shell-command (concat notmuch-command " show --format=mbox " (shell-quote-argument (mapconcat 'identity (notmuch-show-get-message-ids-for-open-messages) " OR ")) diff --git a/test/emacs-address-cleaning.sh b/test/emacs-address-cleaning.sh index 0d85bdc..51018fe 100755 --- a/test/emacs-address-cleaning.sh +++ b/test/emacs-address-cleaning.sh @@ -12,7 +12,6 @@ test_emacs_expect_t \ '(load "emacs-address-cleaning.el") (notmuch-test-address-cleaning-2)' test_begin_subtest "notmuch-test-address-clean part 3" -test_subtest_known_broken test_emacs_expect_t \ '(load "emacs-address-cleaning.el") (notmuch-test-address-cleaning-3)' -- cgit v1.2.3 From 50d65de394cd78bd215918e251646c32eb0c0e52 Mon Sep 17 00:00:00 2001 From: David Edmondson Date: Wed, 25 Jan 2012 13:53:59 +0000 Subject: test: Updated expected output for new `notmuch-show-clean-address'. --- test/emacs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'test') diff --git a/test/emacs b/test/emacs index f150d95..8ca4c8a 100755 --- a/test/emacs +++ b/test/emacs @@ -78,7 +78,7 @@ thread=$(notmuch search --output=threads subject:message-with-invalid-from) test_emacs "(notmuch-show \"$thread\") (test-output)" cat <EXPECTED -"Invalid " From" (2001-01-05) (inbox) +Invalid " From (2001-01-05) (inbox) Subject: message-with-invalid-from To: Notmuch Test Suite Date: Fri, 05 Jan 2001 15:43:57 +0000 -- cgit v1.2.3 From cd03f214470996ec03b126f86afafef5296fd879 Mon Sep 17 00:00:00 2001 From: David Edmondson Date: Wed, 25 Jan 2012 13:54:00 +0000 Subject: emacs: Another special case for `notmuch-show-clean-address'. Remove backslashes. --- emacs/notmuch-show.el | 14 +++++++++----- test/emacs-address-cleaning.el | 6 ++++-- 2 files changed, 13 insertions(+), 7 deletions(-) (limited to 'test') diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index acc2f5e..84ac624 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -315,11 +315,15 @@ unchanged ADDRESS if parsing fails." (t (setq p-address address))) - ;; Remove outer double quotes. They might be required during - ;; transport, but we don't need to see them. - (when (and p-name - (string-match "^\"\\(.*\\)\"$" p-name)) - (setq p-name (match-string 1 p-name))) + ;; Remove elements of the mailbox part that are not relevant for + ;; display, even if they are required during transport. + (when p-name + ;; Outer double quotes. + (when (string-match "^\"\\(.*\\)\"$" p-name) + (setq p-name (match-string 1 p-name))) + + ;; Backslashes. + (setq p-name (replace-regexp-in-string "\\\\" "" p-name))) ;; If the address is 'foo@bar.com ' then show just ;; 'foo@bar.com'. diff --git a/test/emacs-address-cleaning.el b/test/emacs-address-cleaning.el index 19e9e05..3b0b109 100644 --- a/test/emacs-address-cleaning.el +++ b/test/emacs-address-cleaning.el @@ -20,10 +20,12 @@ (let* ((input '("ДБ " "foo (at home) " "foo [at home] " - "Foo Bar")) + "Foo Bar" + "Fred Dibna \\[extraordinaire\\] ")) (expected '("ДБ " "foo (at home) " "foo [at home] " - "Foo Bar")) + "Foo Bar" + "Fred Dibna [extraordinaire] ")) (output (mapcar #'notmuch-show-clean-address input))) (notmuch-test-expect-equal output expected))) -- cgit v1.2.3 From 3f2050ac221a4c940c12442f156f12fff11600c6 Mon Sep 17 00:00:00 2001 From: Aaron Ecay Date: Fri, 3 Feb 2012 11:24:07 +0100 Subject: test: add tests for quoting of MML tags in replies The test is broken at this time; the next commit will introduce a fix. Edited-by: Pieter Praet : Rebased to release branch, moved expected output into the actual test, and fixed "Fcc:" line. --- test/emacs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'test') diff --git a/test/emacs b/test/emacs index f36718e..db8e4ad 100755 --- a/test/emacs +++ b/test/emacs @@ -273,6 +273,27 @@ On 01 Jan 2000 12:00:00 -0000, Notmuch Test Suite w EOF test_expect_equal_file OUTPUT EXPECTED +test_begin_subtest "Quote MML tags in reply" +test_subtest_known_broken +message_id='test-emacs-mml-quoting@message.id' +add_message [id]="$message_id" \ + "[subject]='$test_subtest_name'" \ + '[body]="<#part disposition=inline>"' +test_emacs "(notmuch-show \"id:$message_id\") + (notmuch-show-reply) + (test-output)" +cat <EXPECTED +From: Notmuch Test Suite +To: +Subject: Re: Quote MML tags in reply +In-Reply-To: +Fcc: ${MAIL_DIR}/sent +--text follows this line-- +On Tue, 05 Jan 2001 15:43:57 -0000, Notmuch Test Suite wrote: +> <#!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\"")) -- cgit v1.2.3 From ae438ccd8c77831158c7c30f19710d798ee4a6b4 Mon Sep 17 00:00:00 2001 From: Aaron Ecay Date: Fri, 3 Feb 2012 11:24:08 +0100 Subject: emacs: quote MML tags in replies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Emacs message-mode uses certain text strings to indicate how to attach files to outgoing mail. If these are present in the text of an email, and a user is tricked into replying to the message, the user’s files could be exposed. Edited-by: Pieter Praet : Rebased to release branch. --- NEWS | 11 +++++++++++ emacs/notmuch-mua.el | 7 ++++++- test/emacs | 1 - 3 files changed, 17 insertions(+), 2 deletions(-) (limited to 'test') diff --git a/NEWS b/NEWS index 3d2c2a8..a089e67 100644 --- a/NEWS +++ b/NEWS @@ -11,6 +11,17 @@ Fix error handling in python bindings. exceptions to indicate the error condition. Any subsequent calls into libnotmuch caused segmentation faults. +Quote MML tags in replies + + MML tags are text codes that Emacs uses to indicate attachments + (among other things) in messages being composed. The Emacs + interface did not quote MML tags in the quoted text of a reply. + User could be tricked into replying to a maliciously formatted + message and not editing out the MML tags from the quoted text. This + could lead to files from the user's machine being attached to the + outgoing message. The Emacs interface now quotes these tags in + reply text, so that they do not effect outgoing messages. + Notmuch 0.11 (2012-01-13) ========================= diff --git a/emacs/notmuch-mua.el b/emacs/notmuch-mua.el index 7114e48..3e93d7c 100644 --- a/emacs/notmuch-mua.el +++ b/emacs/notmuch-mua.el @@ -111,7 +111,12 @@ list." (insert body)) (set-buffer-modified-p nil) - (message-goto-body)) + (message-goto-body) + ;; Original message may contain (malicious) MML tags. We must + ;; properly quote them in the reply. Note that using `point-max' + ;; instead of `mark' here is wrong. The buffer may include user's + ;; signature which should not be MML-quoted. + (mml-quote-region (point) (point-max))) (defun notmuch-mua-forward-message () (message-forward) diff --git a/test/emacs b/test/emacs index db8e4ad..2d066ed 100755 --- a/test/emacs +++ b/test/emacs @@ -274,7 +274,6 @@ EOF test_expect_equal_file OUTPUT EXPECTED test_begin_subtest "Quote MML tags in reply" -test_subtest_known_broken message_id='test-emacs-mml-quoting@message.id' add_message [id]="$message_id" \ "[subject]='$test_subtest_name'" \ -- cgit v1.2.3 From 6dec2af55bb393e338586a2a399a659e54240a1f Mon Sep 17 00:00:00 2001 From: Dmitry Kurochkin Date: Sat, 28 Jan 2012 08:47:39 +0400 Subject: test: remove ".sh" extension from the recently added Emacs tests All test files, except for the recently added Emacs tests, do not have ".sh" extension. So remove it from the new test files for consistency. --- test/emacs-address-cleaning | 18 ++++++++++++++++++ test/emacs-address-cleaning.sh | 18 ------------------ test/emacs-test-functions | 9 +++++++++ test/emacs-test-functions.sh | 9 --------- test/notmuch-test | 4 ++-- 5 files changed, 29 insertions(+), 29 deletions(-) create mode 100755 test/emacs-address-cleaning delete mode 100755 test/emacs-address-cleaning.sh create mode 100755 test/emacs-test-functions delete mode 100755 test/emacs-test-functions.sh (limited to 'test') diff --git a/test/emacs-address-cleaning b/test/emacs-address-cleaning new file mode 100755 index 0000000..51018fe --- /dev/null +++ b/test/emacs-address-cleaning @@ -0,0 +1,18 @@ +#!/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 \ + '(load "emacs-address-cleaning.el") (notmuch-test-address-cleaning-1)' + +test_begin_subtest "notmuch-test-address-clean part 2" +test_emacs_expect_t \ + '(load "emacs-address-cleaning.el") (notmuch-test-address-cleaning-2)' + +test_begin_subtest "notmuch-test-address-clean part 3" +test_emacs_expect_t \ + '(load "emacs-address-cleaning.el") (notmuch-test-address-cleaning-3)' + +test_done diff --git a/test/emacs-address-cleaning.sh b/test/emacs-address-cleaning.sh deleted file mode 100755 index 51018fe..0000000 --- a/test/emacs-address-cleaning.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/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 \ - '(load "emacs-address-cleaning.el") (notmuch-test-address-cleaning-1)' - -test_begin_subtest "notmuch-test-address-clean part 2" -test_emacs_expect_t \ - '(load "emacs-address-cleaning.el") (notmuch-test-address-cleaning-2)' - -test_begin_subtest "notmuch-test-address-clean part 3" -test_emacs_expect_t \ - '(load "emacs-address-cleaning.el") (notmuch-test-address-cleaning-3)' - -test_done diff --git a/test/emacs-test-functions b/test/emacs-test-functions new file mode 100755 index 0000000..0e1f9fc --- /dev/null +++ b/test/emacs-test-functions @@ -0,0 +1,9 @@ +#!/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 diff --git a/test/emacs-test-functions.sh b/test/emacs-test-functions.sh deleted file mode 100755 index 0e1f9fc..0000000 --- a/test/emacs-test-functions.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/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 diff --git a/test/notmuch-test b/test/notmuch-test index 3f1740c..ced6b47 100755 --- a/test/notmuch-test +++ b/test/notmuch-test @@ -52,8 +52,8 @@ TESTS=" python hooks argument-parsing - emacs-test-functions.sh - emacs-address-cleaning.sh + emacs-test-functions + emacs-address-cleaning " TESTS=${NOTMUCH_TESTS:=$TESTS} -- cgit v1.2.3 From 32d7b3aabd4cdba0fcf80e95a701bb64d3bf4980 Mon Sep 17 00:00:00 2001 From: David Edmondson Date: Mon, 30 Jan 2012 14:59:54 +0000 Subject: emacs: More address cleaning. Remove outer single-quotes from the mailbox part. Allow for multiple sets of nested single and double quotes. Add more tests. --- emacs/notmuch-show.el | 24 +++++++++++++++++------- test/emacs-address-cleaning.el | 8 ++++++++ 2 files changed, 25 insertions(+), 7 deletions(-) (limited to 'test') diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index 3a1a8c8..26cd221 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -316,15 +316,25 @@ unchanged ADDRESS if parsing fails." (t (setq p-address address))) - ;; Remove elements of the mailbox part that are not relevant for - ;; display, even if they are required during transport. (when p-name - ;; Outer double quotes. - (when (string-match "^\"\\(.*\\)\"$" p-name) - (setq p-name (match-string 1 p-name))) - + ;; Remove elements of the mailbox part that are not relevant for + ;; display, even if they are required during transport: + ;; ;; Backslashes. - (setq p-name (replace-regexp-in-string "\\\\" "" p-name))) + (setq p-name (replace-regexp-in-string "\\\\" "" p-name)) + + ;; Outer single and double quotes, which might be nested. + (loop + with start-of-loop + do (setq start-of-loop p-name) + + when (string-match "^\"\\(.*\\)\"$" p-name) + do (setq p-name (match-string 1 p-name)) + + when (string-match "^'\\(.*\\)'$" p-name) + do (setq p-name (match-string 1 p-name)) + + until (string= start-of-loop p-name))) ;; If the address is 'foo@bar.com ' then show just ;; 'foo@bar.com'. diff --git a/test/emacs-address-cleaning.el b/test/emacs-address-cleaning.el index 3b0b109..8423245 100644 --- a/test/emacs-address-cleaning.el +++ b/test/emacs-address-cleaning.el @@ -21,11 +21,19 @@ "foo (at home) " "foo [at home] " "Foo Bar" + "'Foo Bar' " + "\"'Foo Bar'\" " + "'\"Foo Bar\"' " + "'\"'Foo Bar'\"' " "Fred Dibna \\[extraordinaire\\] ")) (expected '("ДБ " "foo (at home) " "foo [at home] " "Foo Bar" + "Foo Bar " + "Foo Bar " + "Foo Bar " + "Foo Bar " "Fred Dibna [extraordinaire] ")) (output (mapcar #'notmuch-show-clean-address input))) (notmuch-test-expect-equal output expected))) -- cgit v1.2.3 From 69adeb52b1c095f570f590e8a8db7f219b875b35 Mon Sep 17 00:00:00 2001 From: Dmitry Kurochkin Date: Sat, 4 Feb 2012 11:36:36 +0400 Subject: test: add test for hiding Original Message region at beginning of a message The test is currently broken and will be fixed by a subsequent patch. The patch adds a new file for tests of Emacs notmuch-show view. Based on patch by David Edmondson [1]. [1] id:"1327562380-12894-4-git-send-email-dme@dme.org" --- test/emacs-show | 28 ++++++++++++++++++++++++++++ test/notmuch-test | 1 + 2 files changed, 29 insertions(+) create mode 100755 test/emacs-show (limited to 'test') diff --git a/test/emacs-show b/test/emacs-show new file mode 100755 index 0000000..9800575 --- /dev/null +++ b/test/emacs-show @@ -0,0 +1,28 @@ +#!/usr/bin/env bash + +test_description="Testing emacs notmuch-show view" +. test-lib.sh + +test_begin_subtest "Hiding Original Message region at beginning of a message" +test_subtest_known_broken +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 <EXPECTED +Notmuch Test Suite (2001-01-05) (inbox) +Subject: Hiding Original Message region at beginning of a message +To: Notmuch Test Suite +Date: Fri, 05 Jan 2001 15:43:57 +0000 + +[ 2-line hidden original message. Click/Enter to show. ] +EOF + +test_emacs "(notmuch-show \"id:$message_id\") + (test-visible-output)" +test_expect_equal_file OUTPUT EXPECTED + +test_done diff --git a/test/notmuch-test b/test/notmuch-test index ced6b47..e14d34e 100755 --- a/test/notmuch-test +++ b/test/notmuch-test @@ -54,6 +54,7 @@ TESTS=" argument-parsing emacs-test-functions emacs-address-cleaning + emacs-show " TESTS=${NOTMUCH_TESTS:=$TESTS} -- cgit v1.2.3 From 8281430558c1b2eafc847620cd84f5ce40bf6741 Mon Sep 17 00:00:00 2001 From: Dmitry Kurochkin Date: Sat, 4 Feb 2012 11:36:37 +0400 Subject: emacs: fix `notmuch-wash-region-to-button' to work at beginning of buffer `Notmuch-wash-region-to-button' is the function that creates hidden regions with buttons for signatures, citations and original messages. Before the change, it did not work correctly if the to-be-hidden region started at the beginning of a message: the visibility toggle button was hidden as well. The patch fixes this. There are two parts in the fix: * Use `insert-before-markers' instead of `insert' for creating the button, so that it does not get added to the hidden overlay. * Stop using PREFIX argument for adding a newline before the button. The newline should not be added before a button at the beginning of buffer. The corresponding test is fixed now. --- emacs/notmuch-wash.el | 24 ++++++++++++++---------- test/emacs-show | 1 - 2 files changed, 14 insertions(+), 11 deletions(-) (limited to 'test') diff --git a/emacs/notmuch-wash.el b/emacs/notmuch-wash.el index 67143e5..56981d0 100644 --- a/emacs/notmuch-wash.el +++ b/emacs/notmuch-wash.el @@ -136,12 +136,13 @@ collapse the remaining lines into a button.") (lines-count (count-lines (overlay-start overlay) (overlay-end overlay)))) (format label-format lines-count))) -(defun notmuch-wash-region-to-button (msg beg end type prefix) +(defun notmuch-wash-region-to-button (msg beg end type &optional prefix) "Auxiliary function to do the actual making of overlays and buttons BEG and END are buffer locations. TYPE should a string, either -\"citation\" or \"signature\". PREFIX is some arbitrary text to -insert before the button, probably for indentation." +\"citation\" or \"signature\". Optional PREFIX is some arbitrary +text to insert before the button, probably for indentation. Note +that PREFIX should not include a newline." ;; This uses some slightly tricky conversions between strings and ;; symbols because of the way the button code works. Note that @@ -160,12 +161,15 @@ insert before the button, probably for indentation." (overlay-put overlay 'type type) (goto-char (1+ end)) (save-excursion - (goto-char (1- beg)) - (insert prefix) - (insert-button (notmuch-wash-button-label overlay) + (goto-char beg) + (if prefix + (insert-before-markers prefix)) + (let ((button-beg (point))) + (insert-before-markers (notmuch-wash-button-label overlay) "\n") + (make-button button-beg (1- (point)) 'invisibility-spec invis-spec 'overlay overlay - :type button-type)))) + :type button-type))))) (defun notmuch-wash-excerpt-citations (msg depth) "Excerpt citations and up to one signature." @@ -177,7 +181,7 @@ insert before the button, probably for indentation." (msg-end (point-max)) (msg-lines (count-lines msg-start msg-end))) (notmuch-wash-region-to-button - msg msg-start msg-end "original" "\n"))) + msg msg-start msg-end "original"))) (while (and (< (point) (point-max)) (re-search-forward notmuch-wash-citation-regexp nil t)) (let* ((cite-start (match-beginning 0)) @@ -194,7 +198,7 @@ insert before the button, probably for indentation." (forward-line (- notmuch-wash-citation-lines-suffix)) (notmuch-wash-region-to-button msg hidden-start (point-marker) - "citation" "\n"))))) + "citation"))))) (if (and (not (eobp)) (re-search-forward notmuch-wash-signature-regexp nil t)) (let* ((sig-start (match-beginning 0)) @@ -208,7 +212,7 @@ insert before the button, probably for indentation." (overlay-put (make-overlay sig-start-marker sig-end-marker) 'face 'message-cited-text) (notmuch-wash-region-to-button msg sig-start-marker sig-end-marker - "signature" "\n")))))) + "signature")))))) ;; diff --git a/test/emacs-show b/test/emacs-show index 9800575..5700d2e 100755 --- a/test/emacs-show +++ b/test/emacs-show @@ -4,7 +4,6 @@ test_description="Testing emacs notmuch-show view" . test-lib.sh test_begin_subtest "Hiding Original Message region at beginning of a message" -test_subtest_known_broken message_id='OriginalMessageHiding.1@notmuchmail.org' add_message \ [id]="$message_id" \ -- cgit v1.2.3 From 57702cc43017cfd5c5ad65a986ef962f5e40cd59 Mon Sep 17 00:00:00 2001 From: David Bremner Date: Sat, 4 Feb 2012 13:37:33 -0500 Subject: test: Fix up date in MML quoting tests. based on id:"1328264649-27346-3-git-send-email-pieter@praet.org" Commit 66ecd9063 made dates "real", but it hasn't hit release yet. --- test/emacs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'test') diff --git a/test/emacs b/test/emacs index f4a5c81..256a738 100755 --- a/test/emacs +++ b/test/emacs @@ -288,7 +288,7 @@ Subject: Re: Quote MML tags in reply In-Reply-To: Fcc: ${MAIL_DIR}/sent --text follows this line-- -On Tue, 05 Jan 2001 15:43:57 -0000, Notmuch Test Suite wrote: +On Fri, 05 Jan 2001 15:43:57 +0000, Notmuch Test Suite wrote: > <#!part disposition=inline> EOF test_expect_equal_file OUTPUT EXPECTED -- cgit v1.2.3 From 148a96c43d372333060d2bd0eef73a74659f8aa3 Mon Sep 17 00:00:00 2001 From: Dmitry Kurochkin Date: Sun, 5 Feb 2012 11:13:46 +0400 Subject: test: fix emacs tests after tagging operations changes After the recent tagging operations changes, functions bound to "+" and "-" in notmuch-search and notmuch-show views always read input from the minibuffer. Use kbd macros instead of calling them directly. --- test/emacs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'test') diff --git a/test/emacs b/test/emacs index 256a738..b74cfa9 100755 --- a/test/emacs +++ b/test/emacs @@ -101,26 +101,26 @@ 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) - (notmuch-search-add-tag \"tag-from-search-view\")" + (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) - (notmuch-search-remove-tag \"tag-from-search-view\")" + (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 from notmuch-show view" test_emacs "(notmuch-show \"$os_x_darwin_thread\") - (notmuch-show-add-tag \"tag-from-show-view\")" + (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 "Remove tag from notmuch-show view" test_emacs "(notmuch-show \"$os_x_darwin_thread\") - (notmuch-show-remove-tag \"tag-from-show-view\")" + (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)" @@ -128,14 +128,14 @@ 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) - (notmuch-search-add-tag "search-add") - (notmuch-search-add-tag "search-remove") - (notmuch-search-remove-tag "search-remove") + (execute-kbd-macro "+search-add") + (execute-kbd-macro "+search-remove") + (execute-kbd-macro "-search-remove") (notmuch-show "id:\"123..456@example\"") (notmuch-test-wait) - (notmuch-show-add-tag "show-add") - (notmuch-show-add-tag "show-remove") - (notmuch-show-remove-tag "show-remove")' + (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)" -- cgit v1.2.3 From 754ddbb578175b986b10099cb4a11517080579f7 Mon Sep 17 00:00:00 2001 From: Dmitry Kurochkin Date: Sun, 29 Jan 2012 07:36:02 +0400 Subject: test: auto load elisp tests file in test_emacs if available This allows us to simplify shell part of tests written in elisp. --- test/test-lib.sh | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'test') diff --git a/test/test-lib.sh b/test/test-lib.sh index 8158328..0174e93 100644 --- a/test/test-lib.sh +++ b/test/test-lib.sh @@ -943,6 +943,12 @@ test_emacs () { test -z "$missing_dependencies" || return if [ -z "$EMACS_SERVER" ]; then + emacs_tests="$(basename $0).el" + if [ -f "$TEST_DIRECTORY/$emacs_tests" ]; then + load_emacs_tests="--eval '(load \"$emacs_tests\")'" + else + load_emacs_tests= + fi server_name="notmuch-test-suite-$$" # start a detached session with an emacs server # user's TERM is given to dtach which assumes a minimally @@ -950,6 +956,7 @@ test_emacs () { TERM=$ORIGINAL_TERM dtach -n "$TEST_TMPDIR/emacs-dtach-socket.$$" \ sh -c "stty rows 24 cols 80; exec '$TMP_DIRECTORY/run_emacs' \ --no-window-system \ + $load_emacs_tests \ --eval '(setq server-name \"$server_name\")' \ --eval '(server-start)' \ --eval '(orphan-watchdog $$)'" || return -- cgit v1.2.3 From 8d26b8eaac6dc7eebc2658587b2656555244f4b3 Mon Sep 17 00:00:00 2001 From: Dmitry Kurochkin Date: Sun, 29 Jan 2012 07:36:03 +0400 Subject: test: remove explicit loading of elisp tests in emacs-address-cleaning It is no longer needed, since elisp tests files are auto loaded now. --- test/emacs-address-cleaning | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'test') diff --git a/test/emacs-address-cleaning b/test/emacs-address-cleaning index 51018fe..6ddde5c 100755 --- a/test/emacs-address-cleaning +++ b/test/emacs-address-cleaning @@ -4,15 +4,12 @@ test_description="emacs address cleaning" . test-lib.sh test_begin_subtest "notmuch-test-address-clean part 1" -test_emacs_expect_t \ - '(load "emacs-address-cleaning.el") (notmuch-test-address-cleaning-1)' +test_emacs_expect_t '(notmuch-test-address-cleaning-1)' test_begin_subtest "notmuch-test-address-clean part 2" -test_emacs_expect_t \ - '(load "emacs-address-cleaning.el") (notmuch-test-address-cleaning-2)' +test_emacs_expect_t '(notmuch-test-address-cleaning-2)' test_begin_subtest "notmuch-test-address-clean part 3" -test_emacs_expect_t \ - '(load "emacs-address-cleaning.el") (notmuch-test-address-cleaning-3)' +test_emacs_expect_t '(notmuch-test-address-cleaning-3)' test_done -- cgit v1.2.3 From c0cd09041208abb6d641279c9ae453e6f2fdf4db Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Sat, 4 Feb 2012 16:24:26 -0500 Subject: show: Simplify new text formatter code This makes the text formatter take advantage of the new code structure. The previously duplicated header logic is now unified, several things that we used to compute repeatedly across different callbacks are now computed once, and the code is simpler overall and 32% shorter. Unifying the header logic causes this to format some dates slightly differently, so the two affected test cases are updated. --- notmuch-show.c | 87 ++++++++++++++---------------------------------------- test/crypto | 2 +- test/thread-naming | 16 +++++----- 3 files changed, 31 insertions(+), 74 deletions(-) (limited to 'test') diff --git a/notmuch-show.c b/notmuch-show.c index 6a890b2..816e0f8 100644 --- a/notmuch-show.c +++ b/notmuch-show.c @@ -727,67 +727,48 @@ format_part_text (const void *ctx, mime_node_t *node, GMimeObject *meta = node->envelope_part ? GMIME_OBJECT (node->envelope_part) : node->part; GMimeContentType *content_type = g_mime_object_get_content_type (meta); + const notmuch_bool_t leaf = GMIME_IS_PART (node->part); + const char *part_type; int i; if (node->envelope_file) { notmuch_message_t *message = node->envelope_file; - const char *headers[] = { - "Subject", "From", "To", "Cc", "Bcc", "Date" - }; - const char *name, *value; - unsigned int i; - - printf ("\fmessage{ "); - printf ("id:%s depth:%d match:%d filename:%s\n", + + part_type = "message"; + printf ("\f%s{ id:%s depth:%d match:%d filename:%s\n", + part_type, notmuch_message_get_message_id (message), indent, notmuch_message_get_flag (message, NOTMUCH_MESSAGE_FLAG_MATCH), notmuch_message_get_filename (message)); - - printf ("\fheader{\n"); - - printf ("%s\n", _get_one_line_summary (ctx, message)); - - for (i = 0; i < ARRAY_SIZE (headers); i++) { - name = headers[i]; - value = notmuch_message_get_header (message, name); - if (value && strlen (value)) - printf ("%s: %s\n", name, value); - } - printf ("\fheader}\n"); } else { GMimeContentDisposition *disposition = g_mime_object_get_content_disposition (meta); const char *cid = g_mime_object_get_content_id (meta); + const char *filename = leaf ? + g_mime_part_get_filename (GMIME_PART (node->part)) : NULL; if (disposition && strcmp (disposition->disposition, GMIME_DISPOSITION_ATTACHMENT) == 0) - { - printf ("\fattachment{ ID: %d", node->part_num); - - } else { - - printf ("\fpart{ ID: %d", node->part_num); - } - - if (GMIME_IS_PART (node->part)) - { - const char *filename = g_mime_part_get_filename (GMIME_PART (node->part)); - if (filename) - printf (", Filename: %s", filename); - } + part_type = "attachment"; + else + part_type = "part"; + printf ("\f%s{ ID: %d", part_type, node->part_num); + if (filename) + printf (", Filename: %s", filename); if (cid) printf (", Content-id: %s", cid); - printf (", Content-type: %s\n", g_mime_content_type_to_string (content_type)); } - if (node->envelope_part) { + if (GMIME_IS_MESSAGE (node->part)) { GMimeMessage *message = GMIME_MESSAGE (node->part); InternetAddressList *recipients; const char *recipients_string; printf ("\fheader{\n"); + if (node->envelope_file) + printf ("%s\n", _get_one_line_summary (ctx, node->envelope_file)); printf ("Subject: %s\n", g_mime_message_get_subject (message)); printf ("From: %s\n", g_mime_message_get_sender (message)); recipients = g_mime_message_get_recipients (message, GMIME_RECIPIENT_TYPE_TO); @@ -800,9 +781,11 @@ format_part_text (const void *ctx, mime_node_t *node, printf ("Cc: %s\n", recipients_string); printf ("Date: %s\n", g_mime_message_get_date_as_string (message)); printf ("\fheader}\n"); + + printf ("\fbody{\n"); } - if (!node->envelope_file) { + if (leaf) { if (g_mime_content_type_is_type (content_type, "text", "*") && !g_mime_content_type_is_type (content_type, "text", "html")) { @@ -810,45 +793,19 @@ format_part_text (const void *ctx, mime_node_t *node, g_mime_stream_file_set_owner (GMIME_STREAM_FILE (stream_stdout), FALSE); show_text_part_content (node->part, stream_stdout); g_object_unref(stream_stdout); - } - else if (g_mime_content_type_is_type (content_type, "multipart", "*") || - g_mime_content_type_is_type (content_type, "message", "rfc822")) - { - /* Do nothing for multipart since its content will be printed - * when recursing. */ - } - else - { + } else { printf ("Non-text part: %s\n", g_mime_content_type_to_string (content_type)); } } - if (GMIME_IS_MESSAGE (node->part)) - printf ("\fbody{\n"); - for (i = 0; i < node->nchildren; i++) format_part_text (ctx, mime_node_child (node, i), indent, params); if (GMIME_IS_MESSAGE (node->part)) printf ("\fbody}\n"); - if (node->envelope_file) { - printf ("\fmessage}\n"); - } else { - GMimeContentDisposition *disposition; - - disposition = g_mime_object_get_content_disposition (meta); - if (disposition && - strcmp (disposition->disposition, GMIME_DISPOSITION_ATTACHMENT) == 0) - { - printf ("\fattachment}\n"); - } - else - { - printf ("\fpart}\n"); - } - } + printf ("\f%s}\n", part_type); } static void diff --git a/test/crypto b/test/crypto index 446a58b..1dbb60a 100755 --- a/test/crypto +++ b/test/crypto @@ -159,7 +159,7 @@ Notmuch Test Suite (2000-01-01) (encrypted inbox) Subject: test encrypted message 001 From: Notmuch Test Suite To: test_suite@notmuchmail.org -Date: 01 Jan 2000 12:00:00 -0000 +Date: Sat, 01 Jan 2000 12:00:00 +0000 header} body{ part{ ID: 1, Content-type: multipart/encrypted diff --git a/test/thread-naming b/test/thread-naming index 2ce9216..942e593 100755 --- a/test/thread-naming +++ b/test/thread-naming @@ -71,7 +71,7 @@ Notmuch Test Suite (2001-01-05) (unread) Subject: thread-naming: Initial thread subject From: Notmuch Test Suite To: Notmuch Test Suite -Date: Fri, 05 Jan 2001 15:43:56 -0000 +Date: Fri, 05 Jan 2001 15:43:56 +0000 header} body{ part{ ID: 1, Content-type: text/plain @@ -85,7 +85,7 @@ Notmuch Test Suite (2001-01-06) (inbox unread) Subject: thread-naming: Older changed subject From: Notmuch Test Suite To: Notmuch Test Suite -Date: Sat, 06 Jan 2001 15:43:56 -0000 +Date: Sat, 06 Jan 2001 15:43:56 +0000 header} body{ part{ ID: 1, Content-type: text/plain @@ -99,7 +99,7 @@ Notmuch Test Suite (2001-01-07) (inbox unread) Subject: thread-naming: Newer changed subject From: Notmuch Test Suite To: Notmuch Test Suite -Date: Sun, 07 Jan 2001 15:43:56 -0000 +Date: Sun, 07 Jan 2001 15:43:56 +0000 header} body{ part{ ID: 1, Content-type: text/plain @@ -113,7 +113,7 @@ Notmuch Test Suite (2001-01-08) (unread) Subject: thread-naming: Final thread subject From: Notmuch Test Suite To: Notmuch Test Suite -Date: Mon, 08 Jan 2001 15:43:56 -0000 +Date: Mon, 08 Jan 2001 15:43:56 +0000 header} body{ part{ ID: 1, Content-type: text/plain @@ -127,7 +127,7 @@ Notmuch Test Suite (2001-01-09) (inbox unread) Subject: Re: thread-naming: Initial thread subject From: Notmuch Test Suite To: Notmuch Test Suite -Date: Tue, 09 Jan 2001 15:43:45 -0000 +Date: Tue, 09 Jan 2001 15:43:45 +0000 header} body{ part{ ID: 1, Content-type: text/plain @@ -141,7 +141,7 @@ Notmuch Test Suite (2001-01-10) (inbox unread) Subject: Aw: thread-naming: Initial thread subject From: Notmuch Test Suite To: Notmuch Test Suite -Date: Wed, 10 Jan 2001 15:43:45 -0000 +Date: Wed, 10 Jan 2001 15:43:45 +0000 header} body{ part{ ID: 1, Content-type: text/plain @@ -155,7 +155,7 @@ Notmuch Test Suite (2001-01-11) (inbox unread) Subject: Vs: thread-naming: Initial thread subject From: Notmuch Test Suite To: Notmuch Test Suite -Date: Thu, 11 Jan 2001 15:43:45 -0000 +Date: Thu, 11 Jan 2001 15:43:45 +0000 header} body{ part{ ID: 1, Content-type: text/plain @@ -169,7 +169,7 @@ Notmuch Test Suite (2001-01-12) (inbox unread) Subject: Sv: thread-naming: Initial thread subject From: Notmuch Test Suite To: Notmuch Test Suite -Date: Fri, 12 Jan 2001 15:43:45 -0000 +Date: Fri, 12 Jan 2001 15:43:45 +0000 header} body{ part{ ID: 1, Content-type: text/plain -- cgit v1.2.3 From 863c1495141084dd1e66a73be35560b2531b71bf Mon Sep 17 00:00:00 2001 From: Tomi Ollila Date: Wed, 15 Feb 2012 11:17:30 +0200 Subject: test: add tests wrt ignoring user-specified files and directories Files and directories which are specified in 'new.ignore' in the config file shouldn't be indexed nor reported by `notmuch new'. This is basically Pieter's work with Austin's comments addressed. --- test/new | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'test') diff --git a/test/new b/test/new index 49f390d..e453684 100755 --- a/test/new +++ b/test/new @@ -153,4 +153,26 @@ rm -rf "${MAIL_DIR}"/two output=$(NOTMUCH_NEW) test_expect_equal "$output" "No new mail. Removed 3 messages." +# 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 +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 +Added 1 new message to the database." + +test_begin_subtest "Ignore files and directories specified in new.ignore" +test_subtest_known_broken +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_done -- cgit v1.2.3 From ce1e720de64270a7cbb4bc3fba2c7fe081de3edc Mon Sep 17 00:00:00 2001 From: Tomi Ollila Date: Wed, 15 Feb 2012 11:17:31 +0200 Subject: add support for user-specified files & directories to ignore A new configuration key 'new.ignore' is used to determine which files and directories user wants not to be scanned as new mails. Mark the corresponding test as no longer broken. This work merges my previous attempts and Andreas Amann's work in id:"ylp7hi23mw8.fsf@tyndall.ie" --- notmuch-client.h | 9 +++++++++ notmuch-config.c | 30 +++++++++++++++++++++++++++++- notmuch-new.c | 45 +++++++++++++++++++++++++++++++++------------ test/new | 1 - 4 files changed, 71 insertions(+), 14 deletions(-) (limited to 'test') diff --git a/notmuch-client.h b/notmuch-client.h index 60828aa..f4a62cc 100644 --- a/notmuch-client.h +++ b/notmuch-client.h @@ -250,6 +250,15 @@ notmuch_config_set_new_tags (notmuch_config_t *config, const char *new_tags[], size_t length); +const char ** +notmuch_config_get_new_ignore (notmuch_config_t *config, + size_t *length); + +void +notmuch_config_set_new_ignore (notmuch_config_t *config, + const char *new_ignore[], + size_t length); + notmuch_bool_t notmuch_config_get_maildir_synchronize_flags (notmuch_config_t *config); diff --git a/notmuch-config.c b/notmuch-config.c index a124e34..1f01128 100644 --- a/notmuch-config.c +++ b/notmuch-config.c @@ -44,7 +44,10 @@ static const char new_config_comment[] = " The following options are supported here:\n" "\n" "\ttags A list (separated by ';') of the tags that will be\n" - "\t added to all messages incorporated by \"notmuch new\".\n"; + "\t added to all messages incorporated by \"notmuch new\".\n" + "\n" + "\tignore A list (separated by ';') of file and directory names\n" + "\t that will not be searched for messages by \"notmuch new\".\n"; static const char user_config_comment[] = " User configuration\n" @@ -105,6 +108,8 @@ struct _notmuch_config { size_t user_other_email_length; const char **new_tags; size_t new_tags_length; + const char **new_ignore; + size_t new_ignore_length; notmuch_bool_t maildir_synchronize_flags; const char **search_exclude_tags; size_t search_exclude_tags_length; @@ -264,6 +269,8 @@ notmuch_config_open (void *ctx, config->user_other_email_length = 0; config->new_tags = NULL; config->new_tags_length = 0; + config->new_ignore = NULL; + config->new_ignore_length = 0; config->maildir_synchronize_flags = TRUE; config->search_exclude_tags = NULL; config->search_exclude_tags_length = 0; @@ -361,6 +368,10 @@ notmuch_config_open (void *ctx, notmuch_config_set_new_tags (config, tags, 2); } + if (notmuch_config_get_new_ignore (config, &tmp) == NULL) { + notmuch_config_set_new_ignore (config, NULL, 0); + } + if (notmuch_config_get_search_exclude_tags (config, &tmp) == NULL) { if (is_new) { const char *tags[] = { "deleted", "spam" }; @@ -609,6 +620,14 @@ notmuch_config_get_new_tags (notmuch_config_t *config, size_t *length) &(config->new_tags_length), length); } +const char ** +notmuch_config_get_new_ignore (notmuch_config_t *config, size_t *length) +{ + return _config_get_list (config, "new", "ignore", + &(config->new_ignore), + &(config->new_ignore_length), length); +} + void notmuch_config_set_user_other_email (notmuch_config_t *config, const char *list[], @@ -627,6 +646,15 @@ notmuch_config_set_new_tags (notmuch_config_t *config, &(config->new_tags)); } +void +notmuch_config_set_new_ignore (notmuch_config_t *config, + const char *list[], + size_t length) +{ + _config_set_list (config, "new", "ignore", list, length, + &(config->new_ignore)); +} + const char ** notmuch_config_get_search_exclude_tags (notmuch_config_t *config, size_t *length) { diff --git a/notmuch-new.c b/notmuch-new.c index 8dbebb3..4f13535 100644 --- a/notmuch-new.c +++ b/notmuch-new.c @@ -39,6 +39,8 @@ typedef struct { int verbose; const char **new_tags; size_t new_tags_length; + const char **new_ignore; + size_t new_ignore_length; int total_files; int processed_files; @@ -181,6 +183,20 @@ _entries_resemble_maildir (struct dirent **entries, int count) return 0; } +/* Test if the file/directory is to be ignored. + */ +static notmuch_bool_t +_entry_in_ignore_list (const char *entry, add_files_state_t *state) +{ + size_t i; + + for (i = 0; i < state->new_ignore_length; i++) + if (strcmp (entry, state->new_ignore[i]) == 0) + return TRUE; + + return FALSE; +} + /* Examine 'path' recursively as follows: * * o Ask the filesystem for the mtime of 'path' (fs_mtime) @@ -320,15 +336,15 @@ add_files_recursive (notmuch_database_t *notmuch, } /* Ignore special directories to avoid infinite recursion. - * Also ignore the .notmuch directory and any "tmp" directory - * that appears within a maildir. + * Also ignore the .notmuch directory, any "tmp" directory + * that appears within a maildir and files/directories + * the user has configured to be ignored. */ - /* XXX: Eventually we'll want more sophistication to let the - * user specify files to be ignored. */ if (strcmp (entry->d_name, ".") == 0 || strcmp (entry->d_name, "..") == 0 || (is_maildir && strcmp (entry->d_name, "tmp") == 0) || - strcmp (entry->d_name, ".notmuch") ==0) + strcmp (entry->d_name, ".notmuch") == 0 || + _entry_in_ignore_list (entry->d_name, state)) { continue; } @@ -369,6 +385,10 @@ add_files_recursive (notmuch_database_t *notmuch, entry = fs_entries[i]; + /* Ignore files & directories user has configured to be ignored */ + if (_entry_in_ignore_list (entry->d_name, state)) + continue; + /* Check if we've walked past any names in db_files or * db_subdirs. If so, these have been deleted. */ while (notmuch_filenames_valid (db_files) && @@ -650,7 +670,7 @@ add_files (notmuch_database_t *notmuch, * initialized to zero by the top-level caller before calling * count_files). */ static void -count_files (const char *path, int *count) +count_files (const char *path, int *count, add_files_state_t *state) { struct dirent *entry = NULL; char *next; @@ -672,13 +692,13 @@ count_files (const char *path, int *count) entry = fs_entries[i++]; /* Ignore special directories to avoid infinite recursion. - * Also ignore the .notmuch directory. + * Also ignore the .notmuch directory and files/directories + * the user has configured to be ignored. */ - /* XXX: Eventually we'll want more sophistication to let the - * user specify files to be ignored. */ if (strcmp (entry->d_name, ".") == 0 || strcmp (entry->d_name, "..") == 0 || - strcmp (entry->d_name, ".notmuch") == 0) + strcmp (entry->d_name, ".notmuch") == 0 || + _entry_in_ignore_list (entry->d_name, state)) { continue; } @@ -699,7 +719,7 @@ count_files (const char *path, int *count) fflush (stdout); } } else if (S_ISDIR (st.st_mode)) { - count_files (next, count); + count_files (next, count, state); } free (next); @@ -841,6 +861,7 @@ notmuch_new_command (void *ctx, int argc, char *argv[]) return 1; 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); add_files_state.synchronize_flags = notmuch_config_get_maildir_synchronize_flags (config); db_path = notmuch_config_get_database_path (config); @@ -856,7 +877,7 @@ notmuch_new_command (void *ctx, int argc, char *argv[]) int count; count = 0; - count_files (db_path, &count); + count_files (db_path, &count, &add_files_state); if (interrupted) return 1; diff --git a/test/new b/test/new index e453684..79a6c97 100755 --- a/test/new +++ b/test/new @@ -167,7 +167,6 @@ Note: Ignoring non-mail file: ${MAIL_DIR}/ignored_file Added 1 new message to the database." test_begin_subtest "Ignore files and directories specified in new.ignore" -test_subtest_known_broken 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. -- cgit v1.2.3 From e3fb62f59b7cf93c818f382a62c37eea2d1b4f74 Mon Sep 17 00:00:00 2001 From: Pieter Praet Date: Wed, 18 Jan 2012 13:19:41 +0100 Subject: test: always report missing prereqs, independent of `--verbose' option When tests are skipped due to missing prereqs, those prereqs are only displayed when running with the `--verbose' option. This is essential information when troubleshooting, so always send to stdout. --- test/test-lib.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'test') diff --git a/test/test-lib.sh b/test/test-lib.sh index 0174e93..063a2b2 100644 --- a/test/test-lib.sh +++ b/test/test-lib.sh @@ -702,8 +702,8 @@ test_skip () { test_check_missing_external_prereqs_ () { if test -n "$test_subtest_missing_external_prereqs_"; then - say_color skip >&3 "missing prerequisites:" - echo "$test_subtest_missing_external_prereqs_" >&3 + say_color skip >&1 "missing prerequisites:" + echo "$test_subtest_missing_external_prereqs_" >&1 test_report_skip_ "$@" else false -- cgit v1.2.3 From b32831e5b8e494da802f7c616c986fcd1e1e7b5f Mon Sep 17 00:00:00 2001 From: Pieter Praet Date: Wed, 1 Feb 2012 21:37:21 +0100 Subject: test: replace occurrences of $PWD with vars that are more stable Thanks to Dmitry Kurochkin for pointing this out: id:"87d39ymyb4.fsf@gmail.com" --- test/emacs | 2 +- test/new | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'test') diff --git a/test/emacs b/test/emacs index b74cfa9..13b0471 100755 --- a/test/emacs +++ b/test/emacs @@ -266,7 +266,7 @@ From: Notmuch Test Suite To: user@example.com Subject: Re: Testing message sent via SMTP In-Reply-To: -Fcc: $(pwd)/mail/sent +Fcc: ${MAIL_DIR}/sent --text follows this line-- On 01 Jan 2000 12:00:00 -0000, Notmuch Test Suite wrote: > This is a test that messages are sent via SMTP diff --git a/test/new b/test/new index 79a6c97..99f9913 100755 --- a/test/new +++ b/test/new @@ -117,10 +117,10 @@ 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}" "$PWD"/actual_maildir +mv "${MAIL_DIR}" "${TMP_DIRECTORY}"/actual_maildir mkdir "${MAIL_DIR}" -ln -s "$PWD"/actual_maildir "${MAIL_DIR}"/symlink +ln -s "${TMP_DIRECTORY}"/actual_maildir "${MAIL_DIR}"/symlink output=$(NOTMUCH_NEW) test_expect_equal "$output" "Added 1 new message to the database." @@ -128,7 +128,7 @@ test_expect_equal "$output" "Added 1 new message to the database." test_begin_subtest "New symlink to a file" generate_message -external_msg_filename="$PWD"/external/"$(basename "$gen_msg_filename")" +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" -- cgit v1.2.3 From e2a68f9941fb903f5db7e7978ec7c6b2ad8158c1 Mon Sep 17 00:00:00 2001 From: Pieter Praet Date: Sun, 19 Feb 2012 21:50:26 +0100 Subject: test: emacs: expand subtest "Stashing in notmuch-show" wrt stashing Mailing List Archive URIs `notmuch-show-stash-mlarchive-link' stashes a URI pointing to the current message at one of the MLAs configured in `notmuch-show-stash-mlarchive-link-alist'. Marked as "broken": fixed in next commit. --- test/emacs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'test') diff --git a/test/emacs b/test/emacs index 13b0471..e8e23dc 100755 --- a/test/emacs +++ b/test/emacs @@ -384,6 +384,7 @@ test_emacs '(notmuch-show "id:f35dbb950911171438k5df6eb56k77b6c0944e2e79ae@mail. test_expect_equal_file OUTPUT $EXPECTED/notmuch-show-thread-with-hidden-messages test_begin_subtest "Stashing in notmuch-show" +test_subtest_known_broken add_message '[date]="Sat, 01 Jan 2000 12:00:00 -0000"' \ '[from]="Some One "' \ '[to]="Some One Else "' \ @@ -402,9 +403,12 @@ test_emacs '(notmuch-show "id:\"bought\"") (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 9) + (dotimes (i 12) (yank) (insert "\n") (rotate-yank-pointer 1)) @@ -420,6 +424,9 @@ 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 -- cgit v1.2.3 From 2f86290aaf6e4b0de54ea75ca17ce129bfbf3730 Mon Sep 17 00:00:00 2001 From: Pieter Praet Date: Sun, 19 Feb 2012 21:50:27 +0100 Subject: emacs: add `notmuch-show-stash-mlarchive-link{, -and-go}' * emacs/notmuch-show.el (notmuch-show-stash-mlarchive-link-alist): New defcustom of type `alist' (key = name, value = URI), containing Mailing List Archive URI's for searching by Message-Id. (notmuch-show-stash-mlarchive-link-default): New defcustom, default MLA to use when `notmuch-show-stash-mlarchive-link' received no user input whatsoever. Available choices are generated using the contents of `notmuch-show-stash-mlarchive-link-alist'. (notmuch-show-stash-map): Added keybinds "l" and "L" for `notmuch-show-stash-mlarchive-link' respectively `notmuch-show-stash-mlarchive-link-and-go'. (notmuch-show-stash-mlarchive-link): New function, stashes a URI pointing to the current message at one of the MLAs configured in `notmuch-show-stash-mlarchive-link-alist'. Prompts user with `completing-read' if not provided with an MLA key. (notmuch-show-stash-mlarchive-link-and-go): New function, uses `notmuch-show-stash-mlarchive-link' to stash a URI, and then visits it using the browser configured in `browse-url-browser-function'. Based on original work [1] by David Edmondson . [1] id:"1327397873-20596-1-git-send-email-dme@dme.org" --- emacs/notmuch-show.el | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++ test/emacs | 1 - 2 files changed, 61 insertions(+), 1 deletion(-) (limited to 'test') diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index 529b674..aa98eff 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -155,6 +155,35 @@ indentation." (make-variable-buffer-local 'notmuch-show-indent-content) (put 'notmuch-show-indent-content 'permanent-local t) +(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=") + ;; FIXME: can these services be searched by `Message-Id' ? + ;; ("MarkMail" . "http://markmail.org/") + ;; ("Nabble" . "http://nabble.com/") + ;; ("opensubscriber" . "http://opensubscriber.com/") + ) + "List of Mailing List Archives to use when stashing links. + +These URIs are concatenated with the current message's +Message-Id in `notmuch-show-stash-mlarchive-link'." + :type '(alist :key-type (string :tag "Name") + :value-type (string :tag "URL")) + :group 'notmuch-show) + +(defcustom notmuch-show-stash-mlarchive-link-default "Gmane" + "Default Mailing List Archive to use when stashing links. + +This is used when `notmuch-show-stash-mlarchive-link' isn't +provided with an MLA argument nor `completing-read' input." + :type `(choice + ,@(mapcar + (lambda (mla) + (list 'const :tag (car mla) :value (car mla))) + notmuch-show-stash-mlarchive-link-alist)) + :group 'notmuch-show) + (defmacro with-current-notmuch-show-message (&rest body) "Evaluate body with current buffer set to the text of current message" `(save-excursion @@ -1149,6 +1178,8 @@ buffer is stored and re-applied after the refresh." (define-key map "s" 'notmuch-show-stash-subject) (define-key map "T" 'notmuch-show-stash-tags) (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) map) "Submap for stash commands") (fset 'notmuch-show-stash-map notmuch-show-stash-map) @@ -1815,6 +1846,36 @@ thread from search." (interactive) (notmuch-common-do-stash (notmuch-show-get-to))) +(defun notmuch-show-stash-mlarchive-link (&optional mla) + "Copy an ML Archive URI for the current message to the kill-ring. + +This presumes that the message is available at the selected Mailing List Archive. + +If optional argument MLA is non-nil, use the provided key instead of prompting +the user (see `notmuch-show-stash-mlarchive-link-alist')." + (interactive) + (notmuch-common-do-stash + (concat (cdr (assoc + (or mla + (let ((completion-ignore-case t)) + (completing-read + "Mailing List Archive: " + notmuch-show-stash-mlarchive-link-alist + nil t nil nil notmuch-show-stash-mlarchive-link-default))) + notmuch-show-stash-mlarchive-link-alist)) + (notmuch-show-get-message-id t)))) + +(defun notmuch-show-stash-mlarchive-link-and-go (&optional mla) + "Copy an ML Archive URI for the current message to the kill-ring and visit it. + +This presumes that the message is available at the selected Mailing List Archive. + +If optional argument MLA is non-nil, use the provided key instead of prompting +the user (see `notmuch-show-stash-mlarchive-link-alist')." + (interactive) + (notmuch-show-stash-mlarchive-link mla) + (browse-url (current-kill 0 t))) + ;; Commands typically bound to buttons. (defun notmuch-show-part-button-default (&optional button) diff --git a/test/emacs b/test/emacs index e8e23dc..dcfc675 100755 --- a/test/emacs +++ b/test/emacs @@ -384,7 +384,6 @@ test_emacs '(notmuch-show "id:f35dbb950911171438k5df6eb56k77b6c0944e2e79ae@mail. test_expect_equal_file OUTPUT $EXPECTED/notmuch-show-thread-with-hidden-messages test_begin_subtest "Stashing in notmuch-show" -test_subtest_known_broken add_message '[date]="Sat, 01 Jan 2000 12:00:00 -0000"' \ '[from]="Some One "' \ '[to]="Some One Else "' \ -- cgit v1.2.3 From 17a06ab990217fe3f8d71d9fd2520bcfbb79d9ed Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Tue, 21 Feb 2012 10:42:32 -0500 Subject: emacs: Reverse the meaning of notmuch-show-refresh-view's argument Consensus seems to be that people prefer that refreshing show buffers retains state by default, rather than resetting it by default. This turns out to be the case in the code, as well. In fact, there's even a test for this that's been marked broken for several months, which this patch finally gets to mark as fixed. --- emacs/notmuch-crypto.el | 4 ++-- emacs/notmuch-show.el | 18 +++++++++--------- test/emacs | 1 - 3 files changed, 11 insertions(+), 12 deletions(-) (limited to 'test') diff --git a/emacs/notmuch-crypto.el b/emacs/notmuch-crypto.el index 972f26e..94da325 100644 --- a/emacs/notmuch-crypto.el +++ b/emacs/notmuch-crypto.el @@ -120,7 +120,7 @@ mode." :notmuch-from from) (insert "\n"))) -(declare-function notmuch-show-refresh-view "notmuch-show" (&optional retain-state)) +(declare-function notmuch-show-refresh-view "notmuch-show" (&optional reset-state)) (defun notmuch-crypto-sigstatus-good-callback (button) (let* ((sigstatus (button-get button :notmuch-sigstatus)) @@ -145,7 +145,7 @@ mode." (insert "\n") (call-process "gpg" nil t t "--list-keys" keyid)) (recenter -1)) - (notmuch-show-refresh-view))) + (notmuch-show-refresh-view t))) (defun notmuch-crypto-insert-encstatus-button (encstatus) (let* ((status (plist-get encstatus :status)) diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index 6d24ed0..dd1fb83 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -990,7 +990,7 @@ current buffer, if possible." (message (if notmuch-show-process-crypto "Processing cryptographic MIME parts." "Not processing cryptographic MIME parts.")) - (notmuch-show-refresh-view t)) + (notmuch-show-refresh-view)) (defun notmuch-show-toggle-elide-non-matching () "Toggle the display of non-matching messages." @@ -999,7 +999,7 @@ current buffer, if possible." (message (if notmuch-show-elide-non-matching-messages "Showing matching messages only." "Showing all messages.")) - (notmuch-show-refresh-view t)) + (notmuch-show-refresh-view)) (defun notmuch-show-toggle-thread-indentation () "Toggle the indentation of threads." @@ -1008,7 +1008,7 @@ current buffer, if possible." (message (if notmuch-show-indent-content "Content is indented." "Content is not indented.")) - (notmuch-show-refresh-view t)) + (notmuch-show-refresh-view)) (defun notmuch-show-insert-tree (tree depth) "Insert the message tree TREE at depth DEPTH in the current thread." @@ -1150,17 +1150,17 @@ This includes: (message "Previously current message not found.")) (notmuch-show-message-adjust))) -(defun notmuch-show-refresh-view (&optional retain-state) +(defun notmuch-show-refresh-view (&optional reset-state) "Refresh the current view. Refreshes the current view, observing changes in display -preferences. If RETAIN-STATE is non-nil then the state of the -buffer is stored and re-applied after the refresh." +preferences. If invoked with a prefix argument (or RESET-STATE is +non-nil) then the state of the buffer (open/closed messages) is +reset based on the original query." (interactive "P") (let ((inhibit-read-only t) - state) - (if retain-state - (setq state (notmuch-show-capture-state))) + (state (unless reset-state + (notmuch-show-capture-state)))) (erase-buffer) (notmuch-show-build-buffer) (if state diff --git a/test/emacs b/test/emacs index dcfc675..7549892 100755 --- a/test/emacs +++ b/test/emacs @@ -462,7 +462,6 @@ test_emacs '(notmuch-show "id:f35dbb950911171438k5df6eb56k77b6c0944e2e79ae@mail. test_expect_equal_file OUTPUT EXPECTED test_begin_subtest "Refresh modified show buffer" -test_subtest_known_broken test_emacs '(notmuch-show "id:f35dbb950911171438k5df6eb56k77b6c0944e2e79ae@mail.gmail.com") (notmuch-show-toggle-message) (notmuch-show-next-message) -- cgit v1.2.3 From 74f8f15adc1e6fce2d3fcc34b7e9ef0b65d926db Mon Sep 17 00:00:00 2001 From: Michal Sojka Date: Fri, 24 Feb 2012 01:33:15 +0100 Subject: test: Add test for searching of uncommonly encoded messages Emails that are encoded differently than as ASCII or UTF-8 are not indexed properly by notmuch. It is not possible to search for non-ASCII words within those messages. --- test/encoding | 9 +++++++++ test/test-lib.sh | 5 +++++ 2 files changed, 14 insertions(+) (limited to 'test') diff --git a/test/encoding b/test/encoding index 33259c1..3992b5c 100755 --- a/test/encoding +++ b/test/encoding @@ -21,4 +21,13 @@ irrelevant body} message}" +test_begin_subtest "Search for ISO-8859-2 encoded message" +test_subtest_known_broken +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) +test_expect_equal "$output" "thread:0000000000000002 2001-01-05 [1/1] Notmuch Test Suite; ISO-8859-2 encoded message (inbox unread)" + test_done diff --git a/test/test-lib.sh b/test/test-lib.sh index 063a2b2..2781506 100644 --- a/test/test-lib.sh +++ b/test/test-lib.sh @@ -356,6 +356,11 @@ ${additional_headers}" ${additional_headers}" fi + if [ ! -z "${template[content-transfer-encoding]}" ]; then + additional_headers="Content-Transfer-Encoding: ${template[content-transfer-encoding]} +${additional_headers}" + fi + # Note that in the way we're setting it above and using it below, # `additional_headers' will also serve as the header / body separator # (empty line in between). -- cgit v1.2.3 From 1093c24dccd5325096531aa5354b89e82307b67a Mon Sep 17 00:00:00 2001 From: Michal Sojka Date: Fri, 24 Feb 2012 08:36:23 +0100 Subject: test: Remove 'broken' flag from encoding test --- test/encoding | 1 - 1 file changed, 1 deletion(-) (limited to 'test') diff --git a/test/encoding b/test/encoding index 3992b5c..f0d073c 100755 --- a/test/encoding +++ b/test/encoding @@ -22,7 +22,6 @@ irrelevant message}" test_begin_subtest "Search for ISO-8859-2 encoded message" -test_subtest_known_broken add_message '[content-type]="text/plain; charset=iso-8859-2"' \ '[content-transfer-encoding]=8bit' \ '[subject]="ISO-8859-2 encoded message"' \ -- cgit v1.2.3 From 6e25ea031fc43dd3a6a9ff00f33526fdd3abc92a Mon Sep 17 00:00:00 2001 From: Daniel Schoepe Date: Fri, 17 Feb 2012 18:48:08 +0400 Subject: emacs: Tests for user-defined sections A new file was added for notmuch-hello tests. --- test/emacs-hello | 47 ++++++++++++++++++++++ test/emacs.expected-output/notmuch-hello | 3 +- .../notmuch-hello-new-section | 4 ++ .../notmuch-hello-no-saved-searches | 3 +- .../notmuch-hello-section-counts | 5 +++ .../notmuch-hello-section-hidden-tag | 4 ++ .../notmuch-hello-section-with-empty | 4 ++ .../emacs.expected-output/notmuch-hello-with-empty | 3 +- test/notmuch-test | 1 + 9 files changed, 71 insertions(+), 3 deletions(-) create mode 100755 test/emacs-hello create mode 100644 test/emacs.expected-output/notmuch-hello-new-section create mode 100644 test/emacs.expected-output/notmuch-hello-section-counts create mode 100644 test/emacs.expected-output/notmuch-hello-section-hidden-tag create mode 100644 test/emacs.expected-output/notmuch-hello-section-with-empty (limited to 'test') diff --git a/test/emacs-hello b/test/emacs-hello new file mode 100755 index 0000000..b235e3a --- /dev/null +++ b/test/emacs-hello @@ -0,0 +1,47 @@ +#!/usr/bin/env bash + +test_description="Testing 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_done diff --git a/test/emacs.expected-output/notmuch-hello b/test/emacs.expected-output/notmuch-hello index 3e59595..1470790 100644 --- a/test/emacs.expected-output/notmuch-hello +++ b/test/emacs.expected-output/notmuch-hello @@ -6,9 +6,10 @@ Saved searches: [edit] Search: . -[Show all tags] +All tags: [show] Type a search query and hit RET to view matching threads. Edit saved searches with the `edit' button. Hit RET or click on a saved search or tag name to view matching threads. `=' to refresh this screen. `s' to search messages. `q' to quit. + Customize this page. diff --git a/test/emacs.expected-output/notmuch-hello-new-section b/test/emacs.expected-output/notmuch-hello-new-section new file mode 100644 index 0000000..c64d712 --- /dev/null +++ b/test/emacs.expected-output/notmuch-hello-new-section @@ -0,0 +1,4 @@ +Test: [hide] + + 52 inbox + diff --git a/test/emacs.expected-output/notmuch-hello-no-saved-searches b/test/emacs.expected-output/notmuch-hello-no-saved-searches index ef0e5d0..05475b1 100644 --- a/test/emacs.expected-output/notmuch-hello-no-saved-searches +++ b/test/emacs.expected-output/notmuch-hello-no-saved-searches @@ -2,9 +2,10 @@ Search: . -[Show all tags] +All tags: [show] Type a search query and hit RET to view matching threads. Edit saved searches with the `edit' button. Hit RET or click on a saved search or tag name to view matching threads. `=' to refresh this screen. `s' to search messages. `q' to quit. + Customize this page. diff --git a/test/emacs.expected-output/notmuch-hello-section-counts b/test/emacs.expected-output/notmuch-hello-section-counts new file mode 100644 index 0000000..9d79659 --- /dev/null +++ b/test/emacs.expected-output/notmuch-hello-section-counts @@ -0,0 +1,5 @@ +Test-with-counts: [hide] + + 2 attachment 7 signed + 7 inbox 7 unread + diff --git a/test/emacs.expected-output/notmuch-hello-section-hidden-tag b/test/emacs.expected-output/notmuch-hello-section-hidden-tag new file mode 100644 index 0000000..3688e7c --- /dev/null +++ b/test/emacs.expected-output/notmuch-hello-section-hidden-tag @@ -0,0 +1,4 @@ +Test-with-filtered: [hide] + + 4 attachment 52 inbox 7 signed + diff --git a/test/emacs.expected-output/notmuch-hello-section-with-empty b/test/emacs.expected-output/notmuch-hello-section-with-empty new file mode 100644 index 0000000..8209fed --- /dev/null +++ b/test/emacs.expected-output/notmuch-hello-section-with-empty @@ -0,0 +1,4 @@ +Test-with-empty: [hide] + + 52 inbox + diff --git a/test/emacs.expected-output/notmuch-hello-with-empty b/test/emacs.expected-output/notmuch-hello-with-empty index 71edba7..5e53222 100644 --- a/test/emacs.expected-output/notmuch-hello-with-empty +++ b/test/emacs.expected-output/notmuch-hello-with-empty @@ -6,9 +6,10 @@ Saved searches: [edit] Search: . -[Show all tags] +All tags: [show] Type a search query and hit RET to view matching threads. Edit saved searches with the `edit' button. Hit RET or click on a saved search or tag name to view matching threads. `=' to refresh this screen. `s' to search messages. `q' to quit. + Customize this page. diff --git a/test/notmuch-test b/test/notmuch-test index e14d34e..f03b594 100755 --- a/test/notmuch-test +++ b/test/notmuch-test @@ -54,6 +54,7 @@ TESTS=" argument-parsing emacs-test-functions emacs-address-cleaning + emacs-hello emacs-show " TESTS=${NOTMUCH_TESTS:=$TESTS} -- cgit v1.2.3 From 2209d7b9520000fbd6941b1e0e8521da90f443c6 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Sun, 19 Feb 2012 19:26:25 -0500 Subject: show: Use consistent header ordering in the JSON format Previously, top-level message headers were printed as Subject, From, To, Date, while embedded message headers were printed From, To, Subject, Date. This makes both cases use the former order and updates the tests accordingly. --- notmuch-show.c | 6 +++--- test/multipart | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'test') diff --git a/notmuch-show.c b/notmuch-show.c index 868b2cd..9ca9882 100644 --- a/notmuch-show.c +++ b/notmuch-show.c @@ -328,6 +328,9 @@ format_headers_message_part_json (GMimeMessage *message) const char *recipients_string; printf ("%s: %s", + json_quote_str (ctx_quote, "Subject"), + json_quote_str (ctx_quote, g_mime_message_get_subject (message))); + printf (", %s: %s", json_quote_str (ctx_quote, "From"), json_quote_str (ctx_quote, g_mime_message_get_sender (message))); recipients = g_mime_message_get_recipients (message, GMIME_RECIPIENT_TYPE_TO); @@ -342,9 +345,6 @@ format_headers_message_part_json (GMimeMessage *message) printf (", %s: %s", json_quote_str (ctx_quote, "Cc"), json_quote_str (ctx_quote, recipients_string)); - printf (", %s: %s", - json_quote_str (ctx_quote, "Subject"), - json_quote_str (ctx_quote, g_mime_message_get_subject (message))); printf (", %s: %s", json_quote_str (ctx_quote, "Date"), json_quote_str (ctx_quote, g_mime_message_get_date_as_string (message))); diff --git a/test/multipart b/test/multipart index 2dd73f5..4d14804 100755 --- a/test/multipart +++ b/test/multipart @@ -325,7 +325,7 @@ cat <EXPECTED {"id": "87liy5ap00.fsf@yoom.home.cworth.org", "match": true, "filename": "${MAIL_DIR}/multipart", "timestamp": 978709437, "date_relative": "2001-01-05", "tags": ["attachment","inbox","signed","unread"], "headers": {"Subject": "Multipart message", "From": "Carl Worth ", "To": "cworth@cworth.org", "Cc": "", "Bcc": "", "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": {"From": "Carl Worth ", "To": "cworth@cworth.org", "Subject": "html message", "Date": "Fri, 05 Jan 2001 15:42:57 +0000"}, "body": [ +{"id": 3, "content-type": "message/rfc822", "content": [{"headers": {"Subject": "html message", "From": "Carl Worth ", "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"}, {"id": 6, "content-type": "text/plain", "content": "This is an embedded message, with a multipart/alternative part.\n"}]}]}]}, @@ -342,7 +342,7 @@ cat <EXPECTED {"id": 1, "content-type": "multipart/signed", "content": [ {"id": 2, "content-type": "multipart/mixed", "content": [ -{"id": 3, "content-type": "message/rfc822", "content": [{"headers": {"From": "Carl Worth ", "To": "cworth@cworth.org", "Subject": "html message", "Date": "Fri, 05 Jan 2001 15:42:57 +0000"}, "body": [ +{"id": 3, "content-type": "message/rfc822", "content": [{"headers": {"Subject": "html message", "From": "Carl Worth ", "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"}, {"id": 6, "content-type": "text/plain", "content": "This is an embedded message, with a multipart/alternative part.\n"}]}]}]}, @@ -358,7 +358,7 @@ echo >>OUTPUT # expect *no* newline at end of output cat <EXPECTED {"id": 2, "content-type": "multipart/mixed", "content": [ -{"id": 3, "content-type": "message/rfc822", "content": [{"headers": {"From": "Carl Worth ", "To": "cworth@cworth.org", "Subject": "html message", "Date": "Fri, 05 Jan 2001 15:42:57 +0000"}, "body": [ +{"id": 3, "content-type": "message/rfc822", "content": [{"headers": {"Subject": "html message", "From": "Carl Worth ", "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"}, {"id": 6, "content-type": "text/plain", "content": "This is an embedded message, with a multipart/alternative part.\n"}]}]}]}, @@ -372,7 +372,7 @@ notmuch show --format=json --part=3 'id:87liy5ap00.fsf@yoom.home.cworth.org' | s echo >>OUTPUT # expect *no* newline at end of output cat <EXPECTED -{"id": 3, "content-type": "message/rfc822", "content": [{"headers": {"From": "Carl Worth ", "To": "cworth@cworth.org", "Subject": "html message", "Date": "Fri, 05 Jan 2001 15:42:57 +0000"}, "body": [ +{"id": 3, "content-type": "message/rfc822", "content": [{"headers": {"Subject": "html message", "From": "Carl Worth ", "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"}, {"id": 6, "content-type": "text/plain", "content": "This is an embedded message, with a multipart/alternative part.\n"}]}]}]} -- cgit v1.2.3 From 86f89385c3bc34cd91002cc057f6a615b6ab76a9 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Sun, 19 Feb 2012 19:26:26 -0500 Subject: show: Unify JSON header output for messages and message parts This has three ramifications: - Blank To and Cc headers are no longer output for messages. - Dates are now canonicalized for messages, which means they always have a day of the week and GMT is printed +0000 (never -0000) - Invalid From message headers are handled slightly differently, since they get parsed by GMime now instead of notmuch. --- notmuch-show.c | 35 +++-------------------------------- test/crypto | 35 ++++++++++++++--------------------- test/emacs | 4 ++-- test/json | 6 +++--- test/maildir-sync | 2 -- test/multipart | 2 +- 6 files changed, 23 insertions(+), 61 deletions(-) (limited to 'test') diff --git a/notmuch-show.c b/notmuch-show.c index 9ca9882..209ff45 100644 --- a/notmuch-show.c +++ b/notmuch-show.c @@ -291,36 +291,7 @@ format_headers_message_part_text (GMimeMessage *message) } static void -format_headers_json (const void *ctx, notmuch_message_t *message) -{ - const char *headers[] = { - "Subject", "From", "To", "Cc", "Bcc", "Date" - }; - const char *name, *value; - unsigned int i; - int first_header = 1; - void *ctx_quote = talloc_new (ctx); - - for (i = 0; i < ARRAY_SIZE (headers); i++) { - name = headers[i]; - value = notmuch_message_get_header (message, name); - if (value) - { - if (!first_header) - fputs (", ", stdout); - first_header = 0; - - printf ("%s: %s", - json_quote_str (ctx_quote, name), - json_quote_str (ctx_quote, value)); - } - } - - talloc_free (ctx_quote); -} - -static void -format_headers_message_part_json (GMimeMessage *message) +format_headers_json (GMimeMessage *message) { void *ctx = talloc_new (NULL); void *ctx_quote = talloc_new (ctx); @@ -690,7 +661,7 @@ format_part_json (const void *ctx, mime_node_t *node, notmuch_bool_t first) format_message_json (ctx, node->envelope_file); printf ("\"headers\": {"); - format_headers_json (ctx, node->envelope_file); + format_headers_json (GMIME_MESSAGE (node->part)); printf ("}"); printf (", \"body\": ["); @@ -778,7 +749,7 @@ format_part_json (const void *ctx, mime_node_t *node, notmuch_bool_t first) if (GMIME_IS_MESSAGE (node->part)) { printf ("\"headers\": {"); - format_headers_message_part_json (GMIME_MESSAGE (node->part)); + format_headers_json (GMIME_MESSAGE (node->part)); printf ("}"); printf (", \"body\": ["); diff --git a/test/crypto b/test/crypto index 1dbb60a..7e774c8 100755 --- a/test/crypto +++ b/test/crypto @@ -50,9 +50,8 @@ expected='[[[{"id": "XXXXX", "headers": {"Subject": "test signed message 001", "From": "Notmuch Test Suite ", "To": "test_suite@notmuchmail.org", - "Cc": "", - "Bcc": "", - "Date": "01 Jan 2000 12:00:00 -0000"}, + "Date": "Sat, + 01 Jan 2000 12:00:00 +0000"}, "body": [{"id": 1, "sigstatus": [{"status": "good", "fingerprint": "'$FINGERPRINT'", @@ -84,9 +83,8 @@ expected='[[[{"id": "XXXXX", "headers": {"Subject": "test signed message 001", "From": "Notmuch Test Suite ", "To": "test_suite@notmuchmail.org", - "Cc": "", - "Bcc": "", - "Date": "01 Jan 2000 12:00:00 -0000"}, + "Date": "Sat, + 01 Jan 2000 12:00:00 +0000"}, "body": [{"id": 1, "sigstatus": [{"status": "good", "fingerprint": "'$FINGERPRINT'", @@ -120,9 +118,8 @@ expected='[[[{"id": "XXXXX", "headers": {"Subject": "test signed message 001", "From": "Notmuch Test Suite ", "To": "test_suite@notmuchmail.org", - "Cc": "", - "Bcc": "", - "Date": "01 Jan 2000 12:00:00 -0000"}, + "Date": "Sat, + 01 Jan 2000 12:00:00 +0000"}, "body": [{"id": 1, "sigstatus": [{"status": "error", "keyid": "'$(echo $FINGERPRINT | cut -c 25-)'", @@ -194,9 +191,8 @@ expected='[[[{"id": "XXXXX", "headers": {"Subject": "test encrypted message 001", "From": "Notmuch Test Suite ", "To": "test_suite@notmuchmail.org", - "Cc": "", - "Bcc": "", - "Date": "01 Jan 2000 12:00:00 -0000"}, + "Date": "Sat, + 01 Jan 2000 12:00:00 +0000"}, "body": [{"id": 1, "encstatus": [{"status": "good"}], "sigstatus": [], @@ -249,9 +245,8 @@ expected='[[[{"id": "XXXXX", "headers": {"Subject": "test encrypted message 001", "From": "Notmuch Test Suite ", "To": "test_suite@notmuchmail.org", - "Cc": "", - "Bcc": "", - "Date": "01 Jan 2000 12:00:00 -0000"}, + "Date": "Sat, + 01 Jan 2000 12:00:00 +0000"}, "body": [{"id": 1, "encstatus": [{"status": "bad"}], "content-type": "multipart/encrypted", @@ -284,9 +279,8 @@ expected='[[[{"id": "XXXXX", "headers": {"Subject": "test encrypted message 002", "From": "Notmuch Test Suite ", "To": "test_suite@notmuchmail.org", - "Cc": "", - "Bcc": "", - "Date": "01 Jan 2000 12:00:00 -0000"}, + "Date": "Sat, + 01 Jan 2000 12:00:00 +0000"}, "body": [{"id": 1, "encstatus": [{"status": "good"}], "sigstatus": [{"status": "good", @@ -339,9 +333,8 @@ expected='[[[{"id": "XXXXX", "headers": {"Subject": "test signed message 001", "From": "Notmuch Test Suite ", "To": "test_suite@notmuchmail.org", - "Cc": "", - "Bcc": "", - "Date": "01 Jan 2000 12:00:00 -0000"}, + "Date": "Sat, + 01 Jan 2000 12:00:00 +0000"}, "body": [{"id": 1, "sigstatus": [{"status": "error", "keyid": "6D92612D94E46381", diff --git a/test/emacs b/test/emacs index 7549892..29a489c 100755 --- a/test/emacs +++ b/test/emacs @@ -78,7 +78,7 @@ thread=$(notmuch search --output=threads subject:message-with-invalid-from) test_emacs "(notmuch-show \"$thread\") (test-output)" cat <EXPECTED -Invalid " From (2001-01-05) (inbox) +"Invalid " (2001-01-05) (inbox) Subject: message-with-invalid-from To: Notmuch Test Suite Date: Fri, 05 Jan 2001 15:43:57 +0000 @@ -414,7 +414,7 @@ test_emacs '(notmuch-show "id:\"bought\"") (reverse-region (point-min) (point-max)) (test-output)' cat <EXPECTED -Sat, 01 Jan 2000 12:00:00 -0000 +Sat, 01 Jan 2000 12:00:00 +0000 Some One Some One Else Notmuch diff --git a/test/json b/test/json index 7df4380..1bdffd2 100755 --- a/test/json +++ b/test/json @@ -5,7 +5,7 @@ test_description="--format=json output" test_begin_subtest "Show message: json" add_message "[subject]=\"json-show-subject\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[body]=\"json-show-message\"" output=$(notmuch show --format=json "json-show-message") -test_expect_equal "$output" "[[[{\"id\": \"${gen_msg_id}\", \"match\": true, \"filename\": \"${gen_msg_filename}\", \"timestamp\": 946728000, \"date_relative\": \"2000-01-01\", \"tags\": [\"inbox\",\"unread\"], \"headers\": {\"Subject\": \"json-show-subject\", \"From\": \"Notmuch Test Suite \", \"To\": \"Notmuch Test Suite \", \"Cc\": \"\", \"Bcc\": \"\", \"Date\": \"Sat, 01 Jan 2000 12:00:00 -0000\"}, \"body\": [{\"id\": 1, \"content-type\": \"text/plain\", \"content\": \"json-show-message\n\"}]}, []]]]" +test_expect_equal "$output" "[[[{\"id\": \"${gen_msg_id}\", \"match\": true, \"filename\": \"${gen_msg_filename}\", \"timestamp\": 946728000, \"date_relative\": \"2000-01-01\", \"tags\": [\"inbox\",\"unread\"], \"headers\": {\"Subject\": \"json-show-subject\", \"From\": \"Notmuch Test Suite \", \"To\": \"Notmuch Test Suite \", \"Date\": \"Sat, 01 Jan 2000 12:00:00 +0000\"}, \"body\": [{\"id\": 1, \"content-type\": \"text/plain\", \"content\": \"json-show-message\n\"}]}, []]]]" 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\"" @@ -22,7 +22,7 @@ test_expect_equal "$output" "[{\"thread\": \"XXX\", 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 "$output" "[[[{\"id\": \"${gen_msg_id}\", \"match\": true, \"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 \", \"To\": \"Notmuch Test Suite \", \"Cc\": \"\", \"Bcc\": \"\", \"Date\": \"Sat, 01 Jan 2000 12:00:00 -0000\"}, \"body\": [{\"id\": 1, \"content-type\": \"text/plain\", \"content\": \"jsön-show-méssage\n\"}]}, []]]]" +test_expect_equal "$output" "[[[{\"id\": \"${gen_msg_id}\", \"match\": true, \"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 \", \"To\": \"Notmuch Test Suite \", \"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' @@ -35,7 +35,7 @@ emacs_deliver_message \ (insert \"Message-ID: <$id>\n\")" output=$(notmuch show --format=json "id:$id") filename=$(notmuch search --output=files "id:$id") -test_expect_equal "$output" "[[[{\"id\": \"$id\", \"match\": true, \"filename\": \"$filename\", \"timestamp\": 946728000, \"date_relative\": \"2000-01-01\", \"tags\": [\"inbox\"], \"headers\": {\"Subject\": \"$subject\", \"From\": \"Notmuch Test Suite \", \"To\": \"test_suite@notmuchmail.org\", \"Cc\": \"\", \"Bcc\": \"\", \"Date\": \"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\"}]}]}, []]]]" +test_expect_equal "$output" "[[[{\"id\": \"$id\", \"match\": true, \"filename\": \"$filename\", \"timestamp\": 946728000, \"date_relative\": \"2000-01-01\", \"tags\": [\"inbox\"], \"headers\": {\"Subject\": \"$subject\", \"From\": \"Notmuch Test Suite \", \"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\"}]}]}, []]]]" 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\"" diff --git a/test/maildir-sync b/test/maildir-sync index d5872a5..1ee2db0 100755 --- a/test/maildir-sync +++ b/test/maildir-sync @@ -53,8 +53,6 @@ test_expect_equal "$output" '[[[{"id": "adding-replied-tag@notmuch-test-suite", "headers": {"Subject": "Adding replied tag", "From": "Notmuch Test Suite ", "To": "Notmuch Test Suite ", -"Cc": "", -"Bcc": "", "Date": "Fri, 05 Jan 2001 15:43:57 +0000"}, "body": [{"id": 1, diff --git a/test/multipart b/test/multipart index 4d14804..a3036b4 100755 --- a/test/multipart +++ b/test/multipart @@ -322,7 +322,7 @@ notmuch show --format=json --part=0 'id:87liy5ap00.fsf@yoom.home.cworth.org' | s echo >>OUTPUT # expect *no* newline at end of output cat <EXPECTED -{"id": "87liy5ap00.fsf@yoom.home.cworth.org", "match": true, "filename": "${MAIL_DIR}/multipart", "timestamp": 978709437, "date_relative": "2001-01-05", "tags": ["attachment","inbox","signed","unread"], "headers": {"Subject": "Multipart message", "From": "Carl Worth ", "To": "cworth@cworth.org", "Cc": "", "Bcc": "", "Date": "Fri, 05 Jan 2001 15:43:57 +0000"}, "body": [ +{"id": "87liy5ap00.fsf@yoom.home.cworth.org", "match": true, "filename": "${MAIL_DIR}/multipart", "timestamp": 978709437, "date_relative": "2001-01-05", "tags": ["attachment","inbox","signed","unread"], "headers": {"Subject": "Multipart message", "From": "Carl Worth ", "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 ", "To": "cworth@cworth.org", "Date": "Fri, 05 Jan 2001 15:42:57 +0000"}, "body": [ -- cgit v1.2.3 From 98f5b0f09a816dfe5bc206f8b76c87223437e63d Mon Sep 17 00:00:00 2001 From: Mark Walters Date: Thu, 1 Mar 2012 22:30:35 +0000 Subject: test: add tests for new cli --no-exclude option The tests test the new --no-exclude option to search and count. There were no existing tests for the exclude behaviour for count so added these too. --- test/count | 21 +++++++++++++++++++++ test/search | 5 +++++ 2 files changed, 26 insertions(+) (limited to 'test') diff --git a/test/count b/test/count index 300b171..976fff1 100755 --- a/test/count +++ b/test/count @@ -37,4 +37,25 @@ test_expect_equal \ "0" \ "`notmuch count --output=threads ${SEARCH}`" +test_begin_subtest "count excluding \"deleted\" messages" +notmuch config set search.exclude_tags = deleted +generate_message '[subject]="Not deleted"' +generate_message '[subject]="Another not deleted"' +generate_message '[subject]="Deleted"' +notmuch new > /dev/null +notmuch tag +deleted id:$gen_msg_id +test_expect_equal \ + "2" \ + "`notmuch count subject:deleted`" + +test_begin_subtest "count \"deleted\" messages, exclude overridden" +test_expect_equal \ + "1" \ + "`notmuch count subject:deleted and tag:deleted`" + +test_begin_subtest "count \"deleted\" messages, with --no-exclude" +test_expect_equal \ + "3" \ + "`notmuch count --no-exclude subject:deleted`" + test_done diff --git a/test/search b/test/search index 414be35..3da5d17 100755 --- a/test/search +++ b/test/search @@ -148,6 +148,11 @@ 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 "Don't exclude \"deleted\" messages when --no-exclude specified" +output=$(notmuch search --no-exclude 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)" + test_begin_subtest "Don't exclude \"deleted\" messages from search if not configured" notmuch config set search.exclude_tags output=$(notmuch search subject:deleted | notmuch_search_sanitize) -- cgit v1.2.3 From c440e597f9a32c7050fa0cc553b6166941724588 Mon Sep 17 00:00:00 2001 From: Mark Walters Date: Thu, 1 Mar 2012 22:30:39 +0000 Subject: test: update search test to reflect exclude flag notmuch-search.c now returns all matching threads even if it the match is a search.tag_excluded message (but with a mark indicating this). Update the test to reflect this. --- test/search | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'test') diff --git a/test/search b/test/search index 3da5d17..081f60c 100755 --- a/test/search +++ b/test/search @@ -136,7 +136,8 @@ generate_message '[subject]="Deleted"' notmuch new > /dev/null notmuch tag +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_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Not deleted (inbox unread) +thread:XXX 2001-01-05 [0/1] Notmuch Test Suite; Deleted (deleted inbox unread)" test_begin_subtest "Exclude \"deleted\" messages from search, overridden" output=$(notmuch search subject:deleted and tag:deleted | notmuch_search_sanitize) -- cgit v1.2.3 From c8cf9e92d80f960bb8231b518c6967a7aab7f260 Mon Sep 17 00:00:00 2001 From: Mark Walters Date: Thu, 1 Mar 2012 22:30:41 +0000 Subject: test: update tests to reflect the exclude flag notmuch show outputs the exclude flag so many tests using notmuch show failed. This commit adds "excluded:0" or "excluded: false" to the expected outputs. After this commit there should be no failing tests. --- test/crypto | 9 ++++++++- test/encoding | 2 +- test/json | 6 +++--- test/maildir-sync | 1 + test/multipart | 6 +++--- test/thread-naming | 16 ++++++++-------- 6 files changed, 24 insertions(+), 16 deletions(-) (limited to 'test') diff --git a/test/crypto b/test/crypto index 7e774c8..4de4d2b 100755 --- a/test/crypto +++ b/test/crypto @@ -43,6 +43,7 @@ output=$(notmuch show --format=json --verify subject:"test signed message 001" \ | sed -e 's|"created": [1234567890]*|"created": 946728000|') expected='[[[{"id": "XXXXX", "match": true, + "excluded": false, "filename": "YYYYY", "timestamp": 946728000, "date_relative": "2000-01-01", @@ -76,6 +77,7 @@ output=$(notmuch show --format=json --verify subject:"test signed message 001" \ | sed -e 's|"created": [1234567890]*|"created": 946728000|') expected='[[[{"id": "XXXXX", "match": true, + "excluded": false, "filename": "YYYYY", "timestamp": 946728000, "date_relative": "2000-01-01", @@ -111,6 +113,7 @@ output=$(notmuch show --format=json --verify subject:"test signed message 001" \ | sed -e 's|"created": [1234567890]*|"created": 946728000|') expected='[[[{"id": "XXXXX", "match": true, + "excluded": false, "filename": "YYYYY", "timestamp": 946728000, "date_relative": "2000-01-01", @@ -150,7 +153,7 @@ 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=' message{ id:XXXXX depth:0 match:1 filename:XXXXX +expected=' message{ id:XXXXX depth:0 match:1 excluded:0 filename:XXXXX header{ Notmuch Test Suite (2000-01-01) (encrypted inbox) Subject: test encrypted message 001 @@ -184,6 +187,7 @@ output=$(notmuch show --format=json --decrypt subject:"test encrypted message 00 | sed -e 's|"created": [1234567890]*|"created": 946728000|') expected='[[[{"id": "XXXXX", "match": true, + "excluded": false, "filename": "YYYYY", "timestamp": 946728000, "date_relative": "2000-01-01", @@ -238,6 +242,7 @@ output=$(notmuch show --format=json --decrypt subject:"test encrypted message 00 | sed -e 's|"created": [1234567890]*|"created": 946728000|') expected='[[[{"id": "XXXXX", "match": true, + "excluded": false, "filename": "YYYYY", "timestamp": 946728000, "date_relative": "2000-01-01", @@ -272,6 +277,7 @@ output=$(notmuch show --format=json --decrypt subject:"test encrypted message 00 | sed -e 's|"created": [1234567890]*|"created": 946728000|') expected='[[[{"id": "XXXXX", "match": true, + "excluded": false, "filename": "YYYYY", "timestamp": 946728000, "date_relative": "2000-01-01", @@ -326,6 +332,7 @@ output=$(notmuch show --format=json --verify subject:"test signed message 001" \ | sed -e 's|"created": [1234567890]*|"created": 946728000|') expected='[[[{"id": "XXXXX", "match": true, + "excluded": false, "filename": "YYYYY", "timestamp": 946728000, "date_relative": "2000-01-01", diff --git a/test/encoding b/test/encoding index f0d073c..98abf77 100755 --- a/test/encoding +++ b/test/encoding @@ -6,7 +6,7 @@ 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) -test_expect_equal "$output" " message{ id:msg-001@notmuch-test-suite depth:0 match:1 filename:/XXX/mail/msg-001 +test_expect_equal "$output" " message{ id:msg-001@notmuch-test-suite depth:0 match:1 excluded:0 filename:/XXX/mail/msg-001 header{ Notmuch Test Suite (2001-01-05) (inbox unread) Subject: Test message #1 diff --git a/test/json b/test/json index 1bdffd2..6439788 100755 --- a/test/json +++ b/test/json @@ -5,7 +5,7 @@ test_description="--format=json output" test_begin_subtest "Show message: json" add_message "[subject]=\"json-show-subject\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[body]=\"json-show-message\"" output=$(notmuch show --format=json "json-show-message") -test_expect_equal "$output" "[[[{\"id\": \"${gen_msg_id}\", \"match\": true, \"filename\": \"${gen_msg_filename}\", \"timestamp\": 946728000, \"date_relative\": \"2000-01-01\", \"tags\": [\"inbox\",\"unread\"], \"headers\": {\"Subject\": \"json-show-subject\", \"From\": \"Notmuch Test Suite \", \"To\": \"Notmuch Test Suite \", \"Date\": \"Sat, 01 Jan 2000 12:00:00 +0000\"}, \"body\": [{\"id\": 1, \"content-type\": \"text/plain\", \"content\": \"json-show-message\n\"}]}, []]]]" +test_expect_equal "$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 \", \"To\": \"Notmuch Test Suite \", \"Date\": \"Sat, 01 Jan 2000 12:00:00 +0000\"}, \"body\": [{\"id\": 1, \"content-type\": \"text/plain\", \"content\": \"json-show-message\n\"}]}, []]]]" 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\"" @@ -22,7 +22,7 @@ test_expect_equal "$output" "[{\"thread\": \"XXX\", 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 "$output" "[[[{\"id\": \"${gen_msg_id}\", \"match\": true, \"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 \", \"To\": \"Notmuch Test Suite \", \"Date\": \"Sat, 01 Jan 2000 12:00:00 +0000\"}, \"body\": [{\"id\": 1, \"content-type\": \"text/plain\", \"content\": \"jsön-show-méssage\n\"}]}, []]]]" +test_expect_equal "$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 \", \"To\": \"Notmuch Test Suite \", \"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' @@ -35,7 +35,7 @@ emacs_deliver_message \ (insert \"Message-ID: <$id>\n\")" output=$(notmuch show --format=json "id:$id") filename=$(notmuch search --output=files "id:$id") -test_expect_equal "$output" "[[[{\"id\": \"$id\", \"match\": true, \"filename\": \"$filename\", \"timestamp\": 946728000, \"date_relative\": \"2000-01-01\", \"tags\": [\"inbox\"], \"headers\": {\"Subject\": \"$subject\", \"From\": \"Notmuch Test Suite \", \"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\"}]}]}, []]]]" +test_expect_equal "$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 \", \"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\"}]}]}, []]]]" 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\"" diff --git a/test/maildir-sync b/test/maildir-sync index 1ee2db0..d72ec07 100755 --- a/test/maildir-sync +++ b/test/maildir-sync @@ -46,6 +46,7 @@ test_begin_subtest "notmuch show works with renamed file (without notmuch new)" output=$(notmuch show --format=json id:${gen_msg_id} | filter_show_json) test_expect_equal "$output" '[[[{"id": "adding-replied-tag@notmuch-test-suite", "match": true, +"excluded": false, "filename": "MAIL_DIR/cur/adding-replied-tag:2,RS", "timestamp": 978709437, "date_relative": "2001-01-05", diff --git a/test/multipart b/test/multipart index a3036b4..53782c6 100755 --- a/test/multipart +++ b/test/multipart @@ -108,7 +108,7 @@ 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 <EXPECTED - message{ id:87liy5ap00.fsf@yoom.home.cworth.org depth:0 match:1 filename:${MAIL_DIR}/multipart + message{ id:87liy5ap00.fsf@yoom.home.cworth.org depth:0 match:1 excluded:0 filename:${MAIL_DIR}/multipart header{ Carl Worth (2001-01-05) (attachment inbox signed unread) Subject: Multipart message @@ -322,7 +322,7 @@ notmuch show --format=json --part=0 'id:87liy5ap00.fsf@yoom.home.cworth.org' | s echo >>OUTPUT # expect *no* newline at end of output cat <EXPECTED -{"id": "87liy5ap00.fsf@yoom.home.cworth.org", "match": true, "filename": "${MAIL_DIR}/multipart", "timestamp": 978709437, "date_relative": "2001-01-05", "tags": ["attachment","inbox","signed","unread"], "headers": {"Subject": "Multipart message", "From": "Carl Worth ", "To": "cworth@cworth.org", "Date": "Fri, 05 Jan 2001 15:43:57 +0000"}, "body": [ +{"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 ", "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 ", "To": "cworth@cworth.org", "Date": "Fri, 05 Jan 2001 15:42:57 +0000"}, "body": [ @@ -594,4 +594,4 @@ 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 -test_done +test_done \ No newline at end of file diff --git a/test/thread-naming b/test/thread-naming index 942e593..1a1a48f 100755 --- a/test/thread-naming +++ b/test/thread-naming @@ -65,7 +65,7 @@ test_expect_equal "$output" "thread:XXX 2001-01-12 [6/8] Notmuch Test Suite; t test_begin_subtest 'Test order of messages in "notmuch show"' output=$(notmuch show thread-naming | notmuch_show_sanitize) -test_expect_equal "$output" " message{ id:msg-$(printf "%03d" $first)@notmuch-test-suite depth:0 match:1 filename:/XXX/mail/msg-$(printf "%03d" $first) +test_expect_equal "$output" " message{ id:msg-$(printf "%03d" $first)@notmuch-test-suite depth:0 match:1 excluded:0 filename:/XXX/mail/msg-$(printf "%03d" $first) header{ Notmuch Test Suite (2001-01-05) (unread) Subject: thread-naming: Initial thread subject @@ -79,7 +79,7 @@ This is just a test message (#$first) part} body} message} - message{ id:msg-$(printf "%03d" $((first + 1)))@notmuch-test-suite depth:1 match:1 filename:/XXX/mail/msg-$(printf "%03d" $((first + 1))) + message{ id:msg-$(printf "%03d" $((first + 1)))@notmuch-test-suite depth:1 match:1 excluded:0 filename:/XXX/mail/msg-$(printf "%03d" $((first + 1))) header{ Notmuch Test Suite (2001-01-06) (inbox unread) Subject: thread-naming: Older changed subject @@ -93,7 +93,7 @@ This is just a test message (#$((first + 1))) part} body} message} - message{ id:msg-$(printf "%03d" $((first + 2)))@notmuch-test-suite depth:1 match:1 filename:/XXX/mail/msg-$(printf "%03d" $((first + 2))) + message{ id:msg-$(printf "%03d" $((first + 2)))@notmuch-test-suite depth:1 match:1 excluded:0 filename:/XXX/mail/msg-$(printf "%03d" $((first + 2))) header{ Notmuch Test Suite (2001-01-07) (inbox unread) Subject: thread-naming: Newer changed subject @@ -107,7 +107,7 @@ This is just a test message (#$((first + 2))) part} body} message} - message{ id:msg-$(printf "%03d" $((first + 3)))@notmuch-test-suite depth:1 match:1 filename:/XXX/mail/msg-$(printf "%03d" $((first + 3))) + message{ id:msg-$(printf "%03d" $((first + 3)))@notmuch-test-suite depth:1 match:1 excluded:0 filename:/XXX/mail/msg-$(printf "%03d" $((first + 3))) header{ Notmuch Test Suite (2001-01-08) (unread) Subject: thread-naming: Final thread subject @@ -121,7 +121,7 @@ This is just a test message (#$((first + 3))) part} body} message} - message{ id:msg-$(printf "%03d" $((first + 4)))@notmuch-test-suite depth:1 match:1 filename:/XXX/mail/msg-$(printf "%03d" $((first + 4))) + message{ id:msg-$(printf "%03d" $((first + 4)))@notmuch-test-suite depth:1 match:1 excluded:0 filename:/XXX/mail/msg-$(printf "%03d" $((first + 4))) header{ Notmuch Test Suite (2001-01-09) (inbox unread) Subject: Re: thread-naming: Initial thread subject @@ -135,7 +135,7 @@ This is just a test message (#$((first + 4))) part} body} message} - message{ id:msg-$(printf "%03d" $((first + 5)))@notmuch-test-suite depth:1 match:1 filename:/XXX/mail/msg-$(printf "%03d" $((first + 5))) + message{ id:msg-$(printf "%03d" $((first + 5)))@notmuch-test-suite depth:1 match:1 excluded:0 filename:/XXX/mail/msg-$(printf "%03d" $((first + 5))) header{ Notmuch Test Suite (2001-01-10) (inbox unread) Subject: Aw: thread-naming: Initial thread subject @@ -149,7 +149,7 @@ This is just a test message (#$((first + 5))) part} body} message} - message{ id:msg-$(printf "%03d" $((first + 6)))@notmuch-test-suite depth:1 match:1 filename:/XXX/mail/msg-$(printf "%03d" $((first + 6))) + message{ id:msg-$(printf "%03d" $((first + 6)))@notmuch-test-suite depth:1 match:1 excluded:0 filename:/XXX/mail/msg-$(printf "%03d" $((first + 6))) header{ Notmuch Test Suite (2001-01-11) (inbox unread) Subject: Vs: thread-naming: Initial thread subject @@ -163,7 +163,7 @@ This is just a test message (#$((first + 6))) part} body} message} - message{ id:msg-$(printf "%03d" $((first + 7)))@notmuch-test-suite depth:1 match:1 filename:/XXX/mail/msg-$(printf "%03d" $((first + 7))) + message{ id:msg-$(printf "%03d" $((first + 7)))@notmuch-test-suite depth:1 match:1 excluded:0 filename:/XXX/mail/msg-$(printf "%03d" $((first + 7))) header{ Notmuch Test Suite (2001-01-12) (inbox unread) Subject: Sv: thread-naming: Initial thread subject -- cgit v1.2.3 From f34613ea833196922a38cf04cd2ee766a562a410 Mon Sep 17 00:00:00 2001 From: Thomas Jost Date: Tue, 21 Feb 2012 20:35:35 +0100 Subject: build: Require gmime >= 2.6.7 gmime-2.6 had a bug [1] which made it impossible to tell why a signature verification failed when the signer key was unavailable (empty "sigstatus" field in the JSON output). Since 00b5623d the corresponding test is marked as broken when using gmime-2.6 (2.4 is fine). This bug has been fixed in gmime 2.6.5, which is now the minimal gmime-2.6 version required for building notmuch (gmime-2.4 is still available). As a consequence the version check in test/crypto can be removed. [Added by db] Although less unambigously a bug, Gmime 2.6 prior to 2.6.7 also was more strict about parsing, and rejected messages with initial "From " headers. This restriction is relaxed in [2]. For reasons explained in [3], we want to keep this more relaxed parsing for now. [1] https://bugzilla.gnome.org/show_bug.cgi?id=668085 [2] http://git.gnome.org/browse/gmime/commit/?id=d311f576baf750476e06e9a1367a2dc1793ea7eb [3] id:"1331385931-1610-1-git-send-email-david@tethera.net" --- configure | 4 +++- test/crypto | 2 -- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'test') diff --git a/configure b/configure index dedb7d8..ee0ae73 100755 --- a/configure +++ b/configure @@ -273,9 +273,11 @@ if [ ${have_xapian} = "0" ]; then errors=$((errors + 1)) fi +# If using GMime 2.6, we need to have a version >= 2.6.5 to avoid a +# crypto bug. We need 2.6.7 for permissive "From " header handling. printf "Checking for GMime development files... " have_gmime=0 -for gmimepc in gmime-2.6 gmime-2.4; do +for gmimepc in 'gmime-2.6 >= 2.6.7' gmime-2.4; do if pkg-config --exists $gmimepc; then printf "Yes ($gmimepc).\n" have_gmime=1 diff --git a/test/crypto b/test/crypto index 1dbb60a..6723ef8 100755 --- a/test/crypto +++ b/test/crypto @@ -104,8 +104,6 @@ test_expect_equal \ "$expected" test_begin_subtest "signature verification with signer key unavailable" -# this is broken with current versions of gmime-2.6 -(ldd $(which notmuch) | grep -Fq gmime-2.6) && test_subtest_known_broken # move the gnupghome temporarily out of the way mv "${GNUPGHOME}"{,.bak} output=$(notmuch show --format=json --verify subject:"test signed message 001" \ -- cgit v1.2.3 From d2e96a35a5e5eceec158dc255331b6c524810b83 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Tue, 6 Mar 2012 18:48:37 +0000 Subject: test: Fix typo in test description Part 4 is a multipart, not an html part. --- test/multipart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'test') diff --git a/test/multipart b/test/multipart index 53782c6..0ac96d5 100755 --- a/test/multipart +++ b/test/multipart @@ -496,7 +496,7 @@ test_subtest_known_broken 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 html part" +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 <EXPECTED

This is an embedded message, with a multipart/alternative part.

-- cgit v1.2.3 From 046ab77b1045596ab225296987401fe95eb2fe13 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Tue, 6 Mar 2012 18:48:38 +0000 Subject: test: Fix malformed multipart message Previously, there was only one CRLF between the terminating boundary of the embedded multipart/alternative and the boundary of the containing multipart. However, according the RFC 1341, 7.2.1: The boundary must be followed immediately either by another CRLF and the header fields for the next part, or by two CRLFs, in which case there are no header fields for the next part and The CRLF preceding the encapsulation line is considered part of the boundary so that it is possible to have a part that does not end with a CRLF (line break). Thus, there must be *two* CRLFs between these boundaries: one that ends the terminating boundary and one that begins the enclosing boundary. While GMime accepted the message we had before, it could not produce such a message. --- test/multipart | 1 + 1 file changed, 1 insertion(+) (limited to 'test') diff --git a/test/multipart b/test/multipart index 0ac96d5..e73cd8b 100755 --- a/test/multipart +++ b/test/multipart @@ -46,6 +46,7 @@ Content-Disposition: inline EOF cat embedded_message >> ${MAIL_DIR}/multipart cat <> ${MAIL_DIR}/multipart + --=-=-= Content-Disposition: attachment; filename=attachment -- cgit v1.2.3 From b1130bc71c02efb504ad723b56f86618fd186a67 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Tue, 6 Mar 2012 18:48:43 +0000 Subject: show: Convert raw format to the new self-recursive style, properly support interior parts This is fully compatible for root and leaf parts, but now has proper support for interior parts. This requires some design decisions that were guided by what I would want if I were to save a part. Specifically: - Leaf parts are printed without headers and with transfer decoding. This is what makes sense for saving attachments. (Furthermore, the transfer decoding is necessary since, without the headers, the caller would not be able to interpret non-transfer-decoded output.) - Message parts are printed with their message headers, but without enclosing part headers. This is what makes sense for saving a message as a whole (which is a message part) and for saving attached messages. This is symmetric for whole messages and for attached messages, though we special-case the whole message for performance reasons (and corner-case correctness reasons: given malformed input, GMime may not be able to reproduce it from the parsed representation). - Multipart parts are printed with their headers and all child parts. It's not clear what the best thing to do for multipart is, but this was the most natural to implement and can be justified because such parts can't be interpreted without their headers. As an added benefit, we can move the special-case code for part 0 into the raw formatter. --- notmuch-show.c | 159 ++++++++++++++++++++++++--------------------------------- test/multipart | 74 +++++++++++++++++---------- 2 files changed, 116 insertions(+), 117 deletions(-) (limited to 'test') diff --git a/notmuch-show.c b/notmuch-show.c index 341634d..a7463dc 100644 --- a/notmuch-show.c +++ b/notmuch-show.c @@ -20,9 +20,6 @@ #include "notmuch-client.h" -static void -format_headers_message_part_text (GMimeMessage *message); - static notmuch_status_t format_part_text (const void *ctx, mime_node_t *node, int indent, const notmuch_show_params_t *params); @@ -56,23 +53,16 @@ static const notmuch_show_format_t format_mbox = { .message_set_end = "" }; -static void -format_part_content_raw (GMimeObject *part); +static notmuch_status_t +format_part_raw (unused (const void *ctx), mime_node_t *node, + unused (int indent), + unused (const notmuch_show_params_t *params)); static const notmuch_show_format_t format_raw = { - "", NULL, - "", NULL, - "", NULL, format_headers_message_part_text, "\n", - "", - NULL, - NULL, - NULL, - format_part_content_raw, - NULL, - "", - "", - "", "", - "" + .message_set_start = "", + .part = format_part_raw, + .message_set_sep = "", + .message_set_end = "" }; static const char * @@ -210,27 +200,6 @@ _is_from_line (const char *line) return 0; } -static void -format_headers_message_part_text (GMimeMessage *message) -{ - InternetAddressList *recipients; - const char *recipients_string; - - printf ("Subject: %s\n", g_mime_message_get_subject (message)); - printf ("From: %s\n", g_mime_message_get_sender (message)); - recipients = g_mime_message_get_recipients (message, GMIME_RECIPIENT_TYPE_TO); - recipients_string = internet_address_list_to_string (recipients, 0); - if (recipients_string) - printf ("To: %s\n", - recipients_string); - recipients = g_mime_message_get_recipients (message, GMIME_RECIPIENT_TYPE_CC); - recipients_string = internet_address_list_to_string (recipients, 0); - if (recipients_string) - printf ("Cc: %s\n", - recipients_string); - printf ("Date: %s\n", g_mime_message_get_date_as_string (message)); -} - static void format_headers_json (const void *ctx, GMimeMessage *message) { @@ -733,31 +702,82 @@ format_part_mbox (const void *ctx, mime_node_t *node, unused (int indent), return NOTMUCH_STATUS_SUCCESS; } -static void -format_part_content_raw (GMimeObject *part) +static notmuch_status_t +format_part_raw (unused (const void *ctx), mime_node_t *node, + unused (int indent), + unused (const notmuch_show_params_t *params)) { - if (! GMIME_IS_PART (part)) - return; + if (node->envelope_file) { + /* Special case the entire message to avoid MIME parsing. */ + const char *filename; + FILE *file; + size_t size; + char buf[4096]; + + filename = notmuch_message_get_filename (node->envelope_file); + if (filename == NULL) { + fprintf (stderr, "Error: Cannot get message filename.\n"); + return NOTMUCH_STATUS_FILE_ERROR; + } + + file = fopen (filename, "r"); + if (file == NULL) { + fprintf (stderr, "Error: Cannot open file %s: %s\n", filename, strerror (errno)); + return NOTMUCH_STATUS_FILE_ERROR; + } + + while (!feof (file)) { + size = fread (buf, 1, sizeof (buf), file); + if (ferror (file)) { + fprintf (stderr, "Error: Read failed from %s\n", filename); + fclose (file); + return NOTMUCH_STATUS_FILE_ERROR; + } + + if (fwrite (buf, size, 1, stdout) != 1) { + fprintf (stderr, "Error: Write failed\n"); + fclose (file); + return NOTMUCH_STATUS_FILE_ERROR; + } + } + + fclose (file); + return NOTMUCH_STATUS_SUCCESS; + } GMimeStream *stream_stdout; GMimeStream *stream_filter = NULL; - GMimeDataWrapper *wrapper; stream_stdout = g_mime_stream_file_new (stdout); g_mime_stream_file_set_owner (GMIME_STREAM_FILE (stream_stdout), FALSE); stream_filter = g_mime_stream_filter_new (stream_stdout); - wrapper = g_mime_part_get_content_object (GMIME_PART (part)); + if (GMIME_IS_PART (node->part)) { + /* For leaf parts, we emit only the transfer-decoded + * body. */ + GMimeDataWrapper *wrapper; + wrapper = g_mime_part_get_content_object (GMIME_PART (node->part)); - if (wrapper && stream_filter) - g_mime_data_wrapper_write_to_stream (wrapper, stream_filter); + if (wrapper && stream_filter) + g_mime_data_wrapper_write_to_stream (wrapper, stream_filter); + } else { + /* Write out the whole part. For message parts (the root + * part and embedded message parts), this will be the + * message including its headers (but not the + * encapsulating part's headers). For multipart parts, + * this will include the headers. */ + if (stream_filter) + g_mime_object_write_to_stream (node->part, stream_filter); + } if (stream_filter) g_object_unref (stream_filter); if (stream_stdout) g_object_unref(stream_stdout); + + return NOTMUCH_STATUS_SUCCESS; } static notmuch_status_t @@ -893,50 +913,7 @@ do_show_single (void *ctx, notmuch_message_set_flag (message, NOTMUCH_MESSAGE_FLAG_MATCH, 1); - /* Special case for --format=raw of full single message, just cat out file */ - if (params->raw && 0 == params->part) { - - const char *filename; - FILE *file; - size_t size; - char buf[4096]; - - filename = notmuch_message_get_filename (message); - if (filename == NULL) { - fprintf (stderr, "Error: Cannot message filename.\n"); - return 1; - } - - file = fopen (filename, "r"); - if (file == NULL) { - fprintf (stderr, "Error: Cannot open file %s: %s\n", filename, strerror (errno)); - return 1; - } - - while (!feof (file)) { - size = fread (buf, 1, sizeof (buf), file); - if (ferror (file)) { - fprintf (stderr, "Error: Read failed from %s\n", filename); - fclose (file); - return 1; - } - - if (fwrite (buf, size, 1, stdout) != 1) { - fprintf (stderr, "Error: Write failed\n"); - fclose (file); - return 1; - } - } - - fclose (file); - - return 0; - - } else { - - return show_message (ctx, format, message, 0, params) != NOTMUCH_STATUS_SUCCESS; - - } + return show_message (ctx, format, message, 0, params) != NOTMUCH_STATUS_SUCCESS; } /* Formatted output of threads */ diff --git a/test/multipart b/test/multipart index e73cd8b..afc4fc8 100755 --- a/test/multipart +++ b/test/multipart @@ -450,58 +450,80 @@ 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 -# output should *not* include newline -echo >>OUTPUT -cat <EXPECTED -Subject: html message -From: Carl Worth -To: cworth@cworth.org -Date: Fri, 05 Jan 2001 15:42:57 +0000 - -

This is an embedded message, with a multipart/alternative part.

-This is an embedded message, with a multipart/alternative part. -This is a text attachment. -And this message is signed. - --Carl ------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_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 <EXPECTED -Subject: html message +Content-Type: multipart/mixed; boundary="=-=-=" + +--=-=-= +Content-Type: message/rfc822 +Content-Disposition: inline + From: Carl Worth 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

This is an embedded message, with a multipart/alternative part.

+ +--==-=-== +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" -test_subtest_known_broken - 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 <EXPECTED +From: Carl Worth +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 +

This is an embedded message, with a multipart/alternative part.

+ +--==-=-== +Content-Type: text/plain + This is an embedded message, with a multipart/alternative part. + +--==-=-==-- EOF test_expect_equal_file OUTPUT EXPECTED -- cgit v1.2.3 From 6511b08fb81add535b56a183f278b48a45fc9875 Mon Sep 17 00:00:00 2001 From: Dmitry Kurochkin Date: Sat, 10 Mar 2012 05:24:50 +0400 Subject: test: remove "Generate some messages" test from raw Before the change, the first subtest in raw format tests just generated messages and checked that they are added successfully. This is not really a raw format test, it is creating of environment required for other subtests to run. The patch removes the first subtest from raw and replaces it with bare add_message calls, similar to how it is done in other tests. TODO: we should check that test environment was created successfully. Currently, many tests do add_message(), notmuch new and other calls without checking the results. We should come up with a general solution for this, i.e. if any command during test initialization fails, all tests should be skipped with appropriate error message. --- test/raw | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'test') diff --git a/test/raw b/test/raw index 0171e64..de0b867 100755 --- a/test/raw +++ b/test/raw @@ -3,11 +3,8 @@ test_description='notmuch show --format=raw' . ./test-lib.sh -test_begin_subtest "Generate some messages" -generate_message -generate_message -output=$(NOTMUCH_NEW) -test_expect_equal "$output" "Added 2 new messages to the database." +add_message +add_message test_begin_subtest "Attempt to show multiple raw messages" output=$(notmuch show --format=raw "*" 2>&1) -- cgit v1.2.3 From db97cb5b65dc519d2bd02741a6294fdb7dd74459 Mon Sep 17 00:00:00 2001 From: Dmitry Kurochkin Date: Sat, 10 Mar 2012 05:24:51 +0400 Subject: test: use subtest name for generated message subject by default Before the change, messages generated by generate_message() used "Test message #N" for default subject where N is the generated messages counter. Since message subject is commonly present in expected results, there is a chance of breaking other tests when a new generate_message() call is added. The patch changes default subject value for generated messages to subtest name if it is available. If subtest name is not available (i.e. message is generated during test initialization), the old default value is used (in this case it is fine to have the counter in the subject). Another benefit of this change is a sane default value for subject in generated messages, which would allow to simplify code like: test_begin_subtest "test for a cool feature" add_message [subject]="message for test for a cool feature" --- test/encoding | 2 +- test/search-folder-coherence | 2 +- test/test-lib.sh | 6 +++++- 3 files changed, 7 insertions(+), 3 deletions(-) (limited to 'test') diff --git a/test/encoding b/test/encoding index 98abf77..2e1326e 100755 --- a/test/encoding +++ b/test/encoding @@ -9,7 +9,7 @@ output=$(notmuch show id:${gen_msg_id} 2>&1 | notmuch_show_sanitize) test_expect_equal "$output" " message{ id:msg-001@notmuch-test-suite depth:0 match:1 excluded:0 filename:/XXX/mail/msg-001 header{ Notmuch Test Suite (2001-01-05) (inbox unread) -Subject: Test message #1 +Subject: Message with text of unknown charset From: Notmuch Test Suite To: Notmuch Test Suite Date: Fri, 05 Jan 2001 15:43:57 +0000 diff --git a/test/search-folder-coherence b/test/search-folder-coherence index f8119cb..3f6ec76 100755 --- a/test/search-folder-coherence +++ b/test/search-folder-coherence @@ -32,7 +32,7 @@ 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; Test message #1 (inbox unread)" +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) diff --git a/test/test-lib.sh b/test/test-lib.sh index 2781506..06aaea2 100644 --- a/test/test-lib.sh +++ b/test/test-lib.sh @@ -318,7 +318,11 @@ generate_message () fi if [ -z "${template[subject]}" ]; then - template[subject]="Test message #${gen_msg_cnt}" + if [ -n "$test_subtest_name" ]; then + template[subject]="$test_subtest_name" + else + template[subject]="Test message #${gen_msg_cnt}" + fi fi if [ -z "${template[date]}" ]; then -- cgit v1.2.3 From fb36741bf3e81548a6f742c536f910c783756248 Mon Sep 17 00:00:00 2001 From: Mark Walters Date: Wed, 14 Mar 2012 12:26:52 +0000 Subject: test: the test for the exclude code mistakenly excludes the tag "=" The tests for the exclude code in search and count use the line notmuch config set search.exclude_tags = deleted which actually sets the exclude tags to be "=" and "deleted". Remove the "=" from this line. --- test/count | 2 +- test/search | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'test') diff --git a/test/count b/test/count index 976fff1..b97fc06 100755 --- a/test/count +++ b/test/count @@ -38,7 +38,7 @@ test_expect_equal \ "`notmuch count --output=threads ${SEARCH}`" test_begin_subtest "count excluding \"deleted\" messages" -notmuch config set search.exclude_tags = deleted +notmuch config set search.exclude_tags deleted generate_message '[subject]="Not deleted"' generate_message '[subject]="Another not deleted"' generate_message '[subject]="Deleted"' diff --git a/test/search b/test/search index 081f60c..3e3a462 100755 --- a/test/search +++ b/test/search @@ -130,7 +130,7 @@ 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_begin_subtest "Exclude \"deleted\" messages from search" -notmuch config set search.exclude_tags = deleted +notmuch config set search.exclude_tags deleted generate_message '[subject]="Not deleted"' generate_message '[subject]="Deleted"' notmuch new > /dev/null -- cgit v1.2.3 From 1351aafac1e8c77e6ee3d2f41ac7445d0e07238d Mon Sep 17 00:00:00 2001 From: Mark Walters Date: Wed, 14 Mar 2012 12:26:53 +0000 Subject: test: add tests for message only search This adds three tests for --output=messages searches. One test is for the case when one exclude tag does not occur in the Xapian database. This triggers a Xapian bug in some cases and causes the whole exclusion to fail. The next commit avoids this bug. --- test/search | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'test') diff --git a/test/search b/test/search index 3e3a462..17af6a2 100755 --- a/test/search +++ b/test/search @@ -132,13 +132,30 @@ test_expect_equal "$output" "thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; u test_begin_subtest "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) thread:XXX 2001-01-05 [0/1] Notmuch Test Suite; Deleted (deleted inbox unread)" +test_begin_subtest "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 "Exclude \"deleted\" messages from message search (no-exclude)" +output=$(notmuch search --no-exclude --output=messages subject:deleted | notmuch_search_sanitize) +test_expect_equal "$output" "id:$not_deleted_id +id:$deleted_id" + +test_begin_subtest "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 "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)" -- cgit v1.2.3 From 30172649e8738332edeaf45aa341fe7d20333e8a Mon Sep 17 00:00:00 2001 From: Adam Wolfe Gordon Date: Sun, 18 Mar 2012 10:32:33 -0600 Subject: test: Add broken test for the new JSON reply format. --- test/multipart | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) (limited to 'test') diff --git a/test/multipart b/test/multipart index afc4fc8..e5de5d3 100755 --- a/test/multipart +++ b/test/multipart @@ -612,6 +612,59 @@ Non-text part: text/html EOF test_expect_equal_file OUTPUT EXPECTED +test_begin_subtest "'notmuch reply' to a multipart message with json format" +test_subtest_known_broken +notmuch reply --format=json 'id:87liy5ap00.fsf@yoom.home.cworth.org' | notmuch_json_show_sanitize >OUTPUT +cat <EXPECTED +{"reply-headers": {"Subject": "Re: Multipart message", + "From": "Notmuch Test Suite ", + "To": "Carl Worth , + 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 ", + "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 ", + "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"}, + {"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": "YYYYY", + "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"}]}]}} +EOF +test_expect_equal_file OUTPUT 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 -- cgit v1.2.3 From 1904b01b96c1b731afb9649e7b5bceffce901b88 Mon Sep 17 00:00:00 2001 From: Adam Wolfe Gordon Date: Sun, 18 Mar 2012 10:32:36 -0600 Subject: reply: Add a JSON reply format. This new JSON format for replies includes headers generated for a reply message as well as the headers of the original message. Using this data, a client can intelligently create a reply. For example, the emacs client will be able to create replies with quoted HTML parts by parsing the HTML parts. --- notmuch-client.h | 12 +++++++++--- notmuch-reply.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ notmuch-show.c | 29 +++++++++++++++++++++-------- test/multipart | 1 - 4 files changed, 79 insertions(+), 12 deletions(-) (limited to 'test') diff --git a/notmuch-client.h b/notmuch-client.h index a220fe4..fa04fa2 100644 --- a/notmuch-client.h +++ b/notmuch-client.h @@ -62,7 +62,7 @@ #define STRINGIFY(s) STRINGIFY_(s) #define STRINGIFY_(s) #s -struct mime_node; +typedef struct mime_node mime_node_t; struct notmuch_show_params; typedef struct notmuch_show_format { @@ -191,6 +191,12 @@ show_message_body (notmuch_message_t *message, notmuch_status_t show_one_part (const char *filename, int part); +void +format_part_json (const void *ctx, mime_node_t *node, notmuch_bool_t first); + +void +format_headers_json (const void *ctx, GMimeMessage *message, notmuch_bool_t reply); + char * json_quote_chararray (const void *ctx, const char *str, const size_t len); @@ -288,7 +294,7 @@ debugger_is_active (void); * parts. Message-type parts have one child, multipart-type parts * have multiple children, and leaf parts have zero children. */ -typedef struct mime_node { +struct mime_node { /* The MIME object of this part. This will be a GMimeMessage, * GMimePart, GMimeMultipart, or a subclass of one of these. * @@ -351,7 +357,7 @@ typedef struct mime_node { * number to assign it (or -1 if unknown). */ int next_child; int next_part_num; -} mime_node_t; +}; /* Construct a new MIME node pointing to the root message part of * message. If cryptoctx is non-NULL, it will be used to verify diff --git a/notmuch-reply.c b/notmuch-reply.c index f1478cc..e2b6c25 100644 --- a/notmuch-reply.c +++ b/notmuch-reply.c @@ -604,6 +604,51 @@ notmuch_reply_format_default(void *ctx, return 0; } +static int +notmuch_reply_format_json(void *ctx, + notmuch_config_t *config, + notmuch_query_t *query, + notmuch_show_params_t *params, + notmuch_bool_t reply_all) +{ + GMimeMessage *reply; + notmuch_messages_t *messages; + notmuch_message_t *message; + mime_node_t *node; + + if (notmuch_query_count_messages (query) != 1) { + fprintf (stderr, "Error: search term did not match precisely one message.\n"); + return 1; + } + + messages = notmuch_query_search_messages (query); + message = notmuch_messages_get (messages); + if (mime_node_open (ctx, message, params->cryptoctx, params->decrypt, + &node) != NOTMUCH_STATUS_SUCCESS) + return 1; + + reply = create_reply_message (ctx, config, message, reply_all); + if (!reply) + return 1; + + /* The headers of the reply message we've created */ + printf ("{\"reply-headers\": "); + format_headers_json (ctx, reply, TRUE); + g_object_unref (G_OBJECT (reply)); + reply = NULL; + + /* Start the original */ + printf (", \"original\": "); + + format_part_json (ctx, node, TRUE); + + /* End */ + printf ("}\n"); + notmuch_message_destroy (message); + + return 0; +} + /* This format is currently tuned for a git send-email --notmuch hook */ static int notmuch_reply_format_headers_only(void *ctx, @@ -666,6 +711,7 @@ notmuch_reply_format_headers_only(void *ctx, enum { FORMAT_DEFAULT, + FORMAT_JSON, FORMAT_HEADERS_ONLY, }; @@ -685,6 +731,7 @@ notmuch_reply_command (void *ctx, int argc, char *argv[]) notmuch_opt_desc_t options[] = { { NOTMUCH_OPT_KEYWORD, &format, "format", 'f', (notmuch_keyword_t []){ { "default", FORMAT_DEFAULT }, + { "json", FORMAT_JSON }, { "headers-only", FORMAT_HEADERS_ONLY }, { 0, 0 } } }, { NOTMUCH_OPT_KEYWORD, &reply_all, "reply-to", 'r', @@ -703,6 +750,8 @@ notmuch_reply_command (void *ctx, int argc, char *argv[]) if (format == FORMAT_HEADERS_ONLY) reply_format_func = notmuch_reply_format_headers_only; + else if (format == FORMAT_JSON) + reply_format_func = notmuch_reply_format_json; else reply_format_func = notmuch_reply_format_default; diff --git a/notmuch-show.c b/notmuch-show.c index a7463dc..ff9d427 100644 --- a/notmuch-show.c +++ b/notmuch-show.c @@ -200,8 +200,8 @@ _is_from_line (const char *line) return 0; } -static void -format_headers_json (const void *ctx, GMimeMessage *message) +void +format_headers_json (const void *ctx, GMimeMessage *message, notmuch_bool_t reply) { void *local = talloc_new (ctx); InternetAddressList *recipients; @@ -225,9 +225,22 @@ format_headers_json (const void *ctx, GMimeMessage *message) printf (", %s: %s", json_quote_str (local, "Cc"), json_quote_str (local, recipients_string)); - printf (", %s: %s}", - json_quote_str (local, "Date"), - json_quote_str (local, g_mime_message_get_date_as_string (message))); + + if (reply) { + printf (", %s: %s", + json_quote_str (local, "In-reply-to"), + json_quote_str (local, g_mime_object_get_header (GMIME_OBJECT (message), "In-reply-to"))); + + printf (", %s: %s", + json_quote_str (local, "References"), + json_quote_str (local, g_mime_object_get_header (GMIME_OBJECT (message), "References"))); + } else { + printf (", %s: %s", + json_quote_str (local, "Date"), + json_quote_str (local, g_mime_message_get_date_as_string (message))); + } + + printf ("}"); talloc_free (local); } @@ -538,7 +551,7 @@ format_part_text (const void *ctx, mime_node_t *node, return NOTMUCH_STATUS_SUCCESS; } -static void +void format_part_json (const void *ctx, mime_node_t *node, notmuch_bool_t first) { /* Any changes to the JSON format should be reflected in the file @@ -549,7 +562,7 @@ format_part_json (const void *ctx, mime_node_t *node, notmuch_bool_t first) format_message_json (ctx, node->envelope_file); printf ("\"headers\": "); - format_headers_json (ctx, GMIME_MESSAGE (node->part)); + format_headers_json (ctx, GMIME_MESSAGE (node->part), FALSE); printf (", \"body\": ["); format_part_json (ctx, mime_node_child (node, 0), first); @@ -623,7 +636,7 @@ format_part_json (const void *ctx, mime_node_t *node, notmuch_bool_t first) } else if (GMIME_IS_MESSAGE (node->part)) { printf (", \"content\": [{"); printf ("\"headers\": "); - format_headers_json (local, GMIME_MESSAGE (node->part)); + format_headers_json (local, GMIME_MESSAGE (node->part), FALSE); printf (", \"body\": ["); terminator = "]}]"; diff --git a/test/multipart b/test/multipart index e5de5d3..72d3927 100755 --- a/test/multipart +++ b/test/multipart @@ -613,7 +613,6 @@ EOF test_expect_equal_file OUTPUT EXPECTED test_begin_subtest "'notmuch reply' to a multipart message with json format" -test_subtest_known_broken notmuch reply --format=json 'id:87liy5ap00.fsf@yoom.home.cworth.org' | notmuch_json_show_sanitize >OUTPUT cat <EXPECTED {"reply-headers": {"Subject": "Re: Multipart message", -- cgit v1.2.3 From 8420ba10358dcc1d0d306dd1298f07fae2150e11 Mon Sep 17 00:00:00 2001 From: Adam Wolfe Gordon Date: Sun, 18 Mar 2012 10:32:41 -0600 Subject: test: Add broken tests for new emacs reply functionality Add tests for creating nice replies to multipart messages, including those with HTML parts. These tests are expected to fail for now. --- test/emacs | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) (limited to 'test') diff --git a/test/emacs b/test/emacs index 29a489c..01afdb6 100755 --- a/test/emacs +++ b/test/emacs @@ -273,6 +273,103 @@ On 01 Jan 2000 12:00:00 -0000, Notmuch Test Suite w EOF test_expect_equal_file OUTPUT EXPECTED +test_begin_subtest "Reply within emacs to a multipart/mixed message" +test_subtest_known_broken +test_emacs '(notmuch-show "id:20091118002059.067214ed@hikari") + (notmuch-show-reply) + (test-output)' +cat <EXPECTED +From: Notmuch Test Suite +To: Adrian Perez de Castro , notmuch@notmuchmail.org +Subject: Re: [notmuch] Introducing myself +In-Reply-To: <20091118002059.067214ed@hikari> +Fcc: ${MAIL_DIR}/sent +--text follows this line-- +Adrian Perez de Castro 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 +> 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_subtest_known_broken +test_emacs '(notmuch-show "id:cf0c4d610911171136h1713aa59w9cf9aa31f052ad0a@mail.gmail.com") + (notmuch-show-reply) + (test-output)' +cat <EXPECTED +From: Notmuch Test Suite +To: Alex Botero-Lowry , notmuch@notmuchmail.org +Subject: Re: [notmuch] preliminary FreeBSD support +In-Reply-To: +Fcc: ${MAIL_DIR}/sent +--text follows this line-- +Alex Botero-Lowry 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 "Quote MML tags in reply" message_id='test-emacs-mml-quoting@message.id' add_message [id]="$message_id" \ -- cgit v1.2.3 From 650123510cfa64caf6b20f5239f43433fa6f2941 Mon Sep 17 00:00:00 2001 From: Adam Wolfe Gordon Date: Sun, 18 Mar 2012 10:32:42 -0600 Subject: emacs: Use the new JSON reply format and message-cite-original Use the new JSON reply format to create replies in emacs. Quote HTML parts nicely by using mm-display-part to turn them into displayable text, then quoting them with message-cite-original. This is very useful for users who regularly receive HTML-only email. Use message-mode's message-cite-original function to create the quoted body for reply messages. In order to make this act like the existing notmuch defaults, you will need to set the following in your emacs configuration: message-citation-line-format "On %a, %d %b %Y, %f wrote:" message-citation-line-function 'message-insert-formatted-citation-line The tests have been updated to reflect the (ugly) emacs default. --- emacs/notmuch-lib.el | 30 ++++++++++++ emacs/notmuch-mua.el | 124 +++++++++++++++++++++++++++++++++----------------- emacs/notmuch-show.el | 31 +++---------- test/emacs | 8 ++-- 4 files changed, 123 insertions(+), 70 deletions(-) (limited to 'test') diff --git a/emacs/notmuch-lib.el b/emacs/notmuch-lib.el index 7e3f110..c146748 100644 --- a/emacs/notmuch-lib.el +++ b/emacs/notmuch-lib.el @@ -206,6 +206,36 @@ the user hasn't set this variable with the old or new value." (setq seq (nconc (delete elem seq) (list elem)))))) seq)) +(defun notmuch-parts-filter-by-type (parts type) + "Given a list of message parts, return a list containing the ones matching +the given type." + (remove-if-not + (lambda (part) (notmuch-match-content-type (plist-get part :content-type) type)) + parts)) + +;; Helper for parts which are generally not included in the default +;; JSON output. +(defun notmuch-get-bodypart-internal (message-id part-number process-crypto) + (let ((args '("show" "--format=raw")) + (part-arg (format "--part=%s" part-number))) + (setq args (append args (list part-arg))) + (if process-crypto + (setq args (append args '("--decrypt")))) + (setq args (append args (list message-id))) + (with-temp-buffer + (let ((coding-system-for-read 'no-conversion)) + (progn + (apply 'call-process (append (list notmuch-command nil (list t nil) nil) args)) + (buffer-string)))))) + +(defun notmuch-get-bodypart-content (msg part nth process-crypto) + (or (plist-get part :content) + (notmuch-get-bodypart-internal (concat "id:" (plist-get msg :id)) nth process-crypto))) + +(defun notmuch-plist-to-alist (plist) + (loop for (key value . rest) on plist by #'cddr + collect (cons (substring (symbol-name key) 1) value))) + ;; Compatibility functions for versions of emacs before emacs 23. ;; ;; Both functions here were copied from emacs 23 with the following copyright: diff --git a/emacs/notmuch-mua.el b/emacs/notmuch-mua.el index 13244eb..6aae3a0 100644 --- a/emacs/notmuch-mua.el +++ b/emacs/notmuch-mua.el @@ -19,11 +19,15 @@ ;; ;; Authors: David Edmondson +(require 'json) (require 'message) +(require 'format-spec) (require 'notmuch-lib) (require 'notmuch-address) +(eval-when-compile (require 'cl)) + ;; (defcustom notmuch-mua-send-hook '(notmuch-mua-message-send-hook) @@ -72,54 +76,92 @@ list." (push header message-hidden-headers))) notmuch-mua-hidden-headers)) +(defun notmuch-mua-get-quotable-parts (parts) + (loop for part in parts + if (notmuch-match-content-type (plist-get part :content-type) "multipart/alternative") + collect (let* ((subparts (plist-get part :content)) + (types (mapcar (lambda (part) (plist-get part :content-type)) subparts)) + (chosen-type (car (notmuch-multipart/alternative-choose types)))) + (loop for part in (reverse subparts) + if (notmuch-match-content-type (plist-get part :content-type) chosen-type) + return part)) + else if (notmuch-match-content-type (plist-get part :content-type) "multipart/*") + append (notmuch-mua-get-quotable-parts (plist-get part :content)) + else if (notmuch-match-content-type (plist-get part :content-type) "text/*") + collect part)) + (defun notmuch-mua-reply (query-string &optional sender reply-all) - (let (headers - body - (args '("reply"))) - (if notmuch-show-process-crypto - (setq args (append args '("--decrypt")))) + (let ((args '("reply" "--format=json")) + reply + original) + (when notmuch-show-process-crypto + (setq args (append args '("--decrypt")))) + (if reply-all (setq args (append args '("--reply-to=all"))) (setq args (append args '("--reply-to=sender")))) (setq args (append args (list query-string))) - ;; This make assumptions about the output of `notmuch reply', but - ;; really only that the headers come first followed by a blank - ;; line and then the body. + + ;; Get the reply object as JSON, and parse it into an elisp object. (with-temp-buffer (apply 'call-process (append (list notmuch-command nil (list t t) nil) args)) (goto-char (point-min)) - (if (re-search-forward "^$" nil t) - (save-excursion - (save-restriction - (narrow-to-region (point-min) (point)) - (goto-char (point-min)) - (setq headers (mail-header-extract))))) - (forward-line 1) - ;; Original message may contain (malicious) MML tags. We must - ;; properly quote them in the reply. - (mml-quote-region (point) (point-max)) - (setq body (buffer-substring (point) (point-max)))) - ;; If sender is non-nil, set the From: header to its value. - (when sender - (mail-header-set 'from sender headers)) - (let - ;; Overlay the composition window on that being used to read - ;; the original message. - ((same-window-regexps '("\\*mail .*"))) - (notmuch-mua-mail (mail-header 'to headers) - (mail-header 'subject headers) - (message-headers-to-generate headers t '(to subject)))) - ;; insert the message body - but put it in front of the signature - ;; if one is present - (goto-char (point-max)) - (if (re-search-backward message-signature-separator nil t) + (let ((json-object-type 'plist) + (json-array-type 'list) + (json-false 'nil)) + (setq reply (json-read)))) + + ;; Extract the original message to simplify the following code. + (setq original (plist-get reply :original)) + + ;; Extract the headers of both the reply and the original message. + (let* ((original-headers (plist-get original :headers)) + (reply-headers (plist-get reply :reply-headers))) + + ;; If sender is non-nil, set the From: header to its value. + (when sender + (plist-put reply-headers :From sender)) + (let + ;; Overlay the composition window on that being used to read + ;; the original message. + ((same-window-regexps '("\\*mail .*"))) + (notmuch-mua-mail (plist-get reply-headers :To) + (plist-get reply-headers :Subject) + (notmuch-plist-to-alist reply-headers))) + ;; Insert the message body - but put it in front of the signature + ;; if one is present + (goto-char (point-max)) + (if (re-search-backward message-signature-separator nil t) (forward-line -1) - (goto-char (point-max))) - (insert body) - (push-mark)) - (set-buffer-modified-p nil) - - (message-goto-body)) + (goto-char (point-max))) + + (let ((from (plist-get original-headers :From)) + (date (plist-get original-headers :Date)) + (start (point))) + + ;; message-cite-original constructs a citation line based on the From and Date + ;; headers of the original message, which are assumed to be in the buffer. + (insert "From: " from "\n") + (insert "Date: " date "\n\n") + + ;; Get the parts of the original message that should be quoted; this includes + ;; all the text parts, except the non-preferred ones in a multipart/alternative. + (let ((quotable-parts (notmuch-mua-get-quotable-parts (plist-get original :body)))) + (mapc (lambda (part) + (insert (notmuch-get-bodypart-content original part + (plist-get part :id) + notmuch-show-process-crypto))) + quotable-parts)) + + (set-mark (point)) + (goto-char start) + ;; Quote the original message according to the user's configured style. + (message-cite-original)))) + + (goto-char (point-max)) + (push-mark) + (message-goto-body) + (set-buffer-modified-p nil)) (defun notmuch-mua-forward-message () (message-forward) @@ -145,7 +187,7 @@ OTHER-ARGS are passed through to `message-mail'." (when (not (string= "" user-agent)) (push (cons "User-Agent" user-agent) other-headers)))) - (unless (mail-header 'from other-headers) + (unless (mail-header 'From other-headers) (push (cons "From" (concat (notmuch-user-name) " <" (notmuch-user-primary-email) ">")) other-headers)) @@ -208,7 +250,7 @@ the From: address first." (interactive "P") (let ((other-headers (when (or prompt-for-sender notmuch-always-prompt-for-sender) - (list (cons 'from (notmuch-mua-prompt-for-sender)))))) + (list (cons 'From (notmuch-mua-prompt-for-sender)))))) (notmuch-mua-mail nil nil other-headers))) (defun notmuch-mua-new-forward-message (&optional prompt-for-sender) diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index ed938bf..0cd7d82 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -488,7 +488,7 @@ message at DEPTH in the current thread." (setq notmuch-show-process-crypto ,process-crypto) ;; Always acquires the part via `notmuch part', even if it is ;; available in the JSON output. - (insert (notmuch-show-get-bodypart-internal ,message-id ,nth)) + (insert (notmuch-get-bodypart-internal ,message-id ,nth notmuch-show-process-crypto)) ,@body)))) (defun notmuch-show-save-part (message-id nth &optional filename content-type) @@ -536,7 +536,7 @@ current buffer, if possible." ;; test whether we are able to inline it (which includes both ;; capability and suitability tests). (when (mm-inlined-p handle) - (insert (notmuch-show-get-bodypart-content msg part nth)) + (insert (notmuch-get-bodypart-content msg part nth notmuch-show-process-crypto)) (when (mm-inlinable-p handle) (set-buffer display-buffer) (mm-display-part handle) @@ -613,8 +613,8 @@ current buffer, if possible." ;; times (hundreds!), which results in many calls to ;; `notmuch part'. (unless content - (setq content (notmuch-show-get-bodypart-internal (concat "id:" message-id) - part-number)) + (setq content (notmuch-get-bodypart-internal (concat "id:" message-id) + part-number notmuch-show-process-crypto)) (with-current-buffer w3m-current-buffer (notmuch-show-w3m-cid-store-internal url message-id @@ -734,7 +734,7 @@ current buffer, if possible." ;; insert a header to make this clear. (if (> nth 1) (notmuch-show-insert-part-header nth declared-type content-type (plist-get part :filename))) - (insert (notmuch-show-get-bodypart-content msg part nth)) + (insert (notmuch-get-bodypart-content msg part nth notmuch-show-process-crypto)) (save-excursion (save-restriction (narrow-to-region start (point-max)) @@ -744,7 +744,7 @@ current buffer, if possible." (defun notmuch-show-insert-part-text/calendar (msg part content-type nth depth declared-type) (notmuch-show-insert-part-header nth declared-type content-type (plist-get part :filename)) (insert (with-temp-buffer - (insert (notmuch-show-get-bodypart-content msg part nth)) + (insert (notmuch-get-bodypart-content msg part nth notmuch-show-process-crypto)) (goto-char (point-min)) (let ((file (make-temp-file "notmuch-ical")) result) @@ -806,25 +806,6 @@ current buffer, if possible." (intern (concat "notmuch-show-insert-part-" content-type)))) result)) -;; Helper for parts which are generally not included in the default -;; JSON output. -(defun notmuch-show-get-bodypart-internal (message-id part-number) - (let ((args '("show" "--format=raw")) - (part-arg (format "--part=%s" part-number))) - (setq args (append args (list part-arg))) - (if notmuch-show-process-crypto - (setq args (append args '("--decrypt")))) - (setq args (append args (list message-id))) - (with-temp-buffer - (let ((coding-system-for-read 'no-conversion)) - (progn - (apply 'call-process (append (list notmuch-command nil (list t nil) nil) args)) - (buffer-string)))))) - -(defun notmuch-show-get-bodypart-content (msg part nth) - (or (plist-get part :content) - (notmuch-show-get-bodypart-internal (concat "id:" (plist-get msg :id)) nth))) - ;; (defun notmuch-show-insert-bodypart-internal (msg part content-type nth depth declared-type) diff --git a/test/emacs b/test/emacs index 01afdb6..8a28705 100755 --- a/test/emacs +++ b/test/emacs @@ -268,13 +268,13 @@ Subject: Re: Testing message sent via SMTP In-Reply-To: Fcc: ${MAIL_DIR}/sent --text follows this line-- -On 01 Jan 2000 12:00:00 -0000, Notmuch Test Suite wrote: +Notmuch Test Suite writes: + > This is a test that messages are sent via SMTP EOF test_expect_equal_file OUTPUT EXPECTED test_begin_subtest "Reply within emacs to a multipart/mixed message" -test_subtest_known_broken test_emacs '(notmuch-show "id:20091118002059.067214ed@hikari") (notmuch-show-reply) (test-output)' @@ -334,7 +334,6 @@ EOF test_expect_equal_file OUTPUT EXPECTED test_begin_subtest "Reply within emacs to a multipart/alternative message" -test_subtest_known_broken test_emacs '(notmuch-show "id:cf0c4d610911171136h1713aa59w9cf9aa31f052ad0a@mail.gmail.com") (notmuch-show-reply) (test-output)' @@ -385,7 +384,8 @@ Subject: Re: Quote MML tags in reply In-Reply-To: Fcc: ${MAIL_DIR}/sent --text follows this line-- -On Fri, 05 Jan 2001 15:43:57 +0000, Notmuch Test Suite wrote: +Notmuch Test Suite writes: + > <#!part disposition=inline> EOF test_expect_equal_file OUTPUT EXPECTED -- cgit v1.2.3 From 918b80359727de2dd87f26a252de8faee2eff78c Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 27 Mar 2012 00:04:08 +0300 Subject: test: add test for both adding and removing a tag at the same time The current behaviour is that regardless of the order in which the addition and removal of a tag are specified, the tag is added. Signed-off-by: Jani Nikula --- test/tagging | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'test') diff --git a/test/tagging b/test/tagging index 77202bf..3acf1bc 100755 --- a/test/tagging +++ b/test/tagging @@ -38,4 +38,12 @@ 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 tag4 unread) +thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Two (inbox tag1 tag4 unread)" + test_done -- cgit v1.2.3 From 8e3ff8fb03dc647f1daea4665c35a2214473ced8 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 27 Mar 2012 00:04:09 +0300 Subject: cli: refactor "notmuch tag" data structures for tagging operations To simplify code, keep all tagging operations in a single array instead of separate add and remove arrays. Apply tag changes in the order specified on the command line, instead of first removing and then adding the tags. This results in a minor functional change: If a tag is both added and removed, the last specified operation is now used. Previously the tag was always added. Change the relevant test to reflect the new behaviour. Signed-off-by: Jani Nikula --- notmuch-tag.c | 83 ++++++++++++++++++++++++++++------------------------------- test/tagging | 2 +- 2 files changed, 40 insertions(+), 45 deletions(-) (limited to 'test') diff --git a/notmuch-tag.c b/notmuch-tag.c index 36b9b09..0a6b140 100644 --- a/notmuch-tag.c +++ b/notmuch-tag.c @@ -53,10 +53,14 @@ _escape_tag (char *buf, const char *tag) return buf; } +typedef struct { + const char *tag; + notmuch_bool_t remove; +} tag_operation_t; + static char * -_optimize_tag_query (void *ctx, const char *orig_query_string, char *argv[], - int *add_tags, int add_tags_count, - int *remove_tags, int remove_tags_count) +_optimize_tag_query (void *ctx, const char *orig_query_string, + const tag_operation_t *tag_ops) { /* This is subtler than it looks. Xapian ignores the '-' operator * at the beginning both queries and parenthesized groups and, @@ -71,15 +75,16 @@ _optimize_tag_query (void *ctx, const char *orig_query_string, char *argv[], int i; unsigned int max_tag_len = 0; + /* Don't optimize if there are no tag changes. */ + if (tag_ops[0].tag == NULL) + return talloc_strdup (ctx, orig_query_string); + /* Allocate a buffer for escaping tags. This is large enough to * hold a fully escaped tag with every character doubled plus * enclosing quotes and a NUL. */ - for (i = 0; i < add_tags_count; i++) - if (strlen (argv[add_tags[i]] + 1) > max_tag_len) - max_tag_len = strlen (argv[add_tags[i]] + 1); - for (i = 0; i < remove_tags_count; i++) - if (strlen (argv[remove_tags[i]] + 1) > max_tag_len) - max_tag_len = strlen (argv[remove_tags[i]] + 1); + for (i = 0; tag_ops[i].tag; i++) + if (strlen (tag_ops[i].tag) > max_tag_len) + max_tag_len = strlen (tag_ops[i].tag); escaped = talloc_array(ctx, char, max_tag_len * 2 + 3); if (!escaped) return NULL; @@ -90,16 +95,11 @@ _optimize_tag_query (void *ctx, const char *orig_query_string, char *argv[], else query_string = talloc_asprintf (ctx, "( %s ) and (", orig_query_string); - for (i = 0; i < add_tags_count && query_string; i++) { + for (i = 0; tag_ops[i].tag && query_string; i++) { query_string = talloc_asprintf_append_buffer ( - query_string, "%snot tag:%s", join, - _escape_tag (escaped, argv[add_tags[i]] + 1)); - join = " or "; - } - for (i = 0; i < remove_tags_count && query_string; i++) { - query_string = talloc_asprintf_append_buffer ( - query_string, "%stag:%s", join, - _escape_tag (escaped, argv[remove_tags[i]] + 1)); + query_string, "%s%stag:%s", join, + tag_ops[i].remove ? "" : "not ", + _escape_tag (escaped, tag_ops[i].tag)); join = " or "; } @@ -113,9 +113,8 @@ _optimize_tag_query (void *ctx, const char *orig_query_string, char *argv[], int notmuch_tag_command (void *ctx, int argc, char *argv[]) { - int *add_tags, *remove_tags; - int add_tags_count = 0; - int remove_tags_count = 0; + tag_operation_t *tag_ops; + int tag_ops_count = 0; char *query_string; notmuch_config_t *config; notmuch_database_t *notmuch; @@ -133,35 +132,33 @@ notmuch_tag_command (void *ctx, int argc, char *argv[]) action.sa_flags = SA_RESTART; sigaction (SIGINT, &action, NULL); - add_tags = talloc_size (ctx, argc * sizeof (int)); - if (add_tags == NULL) { - fprintf (stderr, "Out of memory.\n"); - return 1; - } + argc--; argv++; /* skip subcommand argument */ - remove_tags = talloc_size (ctx, argc * sizeof (int)); - if (remove_tags == NULL) { + /* Array of tagging operations (add or remove), terminated with an + * empty element. */ + tag_ops = talloc_array (ctx, tag_operation_t, argc + 1); + if (tag_ops == NULL) { fprintf (stderr, "Out of memory.\n"); return 1; } - argc--; argv++; /* skip subcommand argument */ - for (i = 0; i < argc; i++) { if (strcmp (argv[i], "--") == 0) { i++; break; } - if (argv[i][0] == '+') { - add_tags[add_tags_count++] = i; - } else if (argv[i][0] == '-') { - remove_tags[remove_tags_count++] = i; + if (argv[i][0] == '+' || argv[i][0] == '-') { + tag_ops[tag_ops_count].tag = argv[i] + 1; + tag_ops[tag_ops_count].remove = (argv[i][0] == '-'); + tag_ops_count++; } else { break; } } - if (add_tags_count == 0 && remove_tags_count == 0) { + tag_ops[tag_ops_count].tag = NULL; + + if (tag_ops_count == 0) { fprintf (stderr, "Error: 'notmuch tag' requires at least one tag to add or remove.\n"); return 1; } @@ -175,9 +172,7 @@ notmuch_tag_command (void *ctx, int argc, char *argv[]) /* Optimize the query so it excludes messages that already have * the specified set of tags. */ - query_string = _optimize_tag_query (ctx, query_string, argv, - add_tags, add_tags_count, - remove_tags, remove_tags_count); + query_string = _optimize_tag_query (ctx, query_string, tag_ops); if (query_string == NULL) { fprintf (stderr, "Out of memory.\n"); return 1; @@ -211,12 +206,12 @@ notmuch_tag_command (void *ctx, int argc, char *argv[]) notmuch_message_freeze (message); - for (i = 0; i < remove_tags_count; i++) - notmuch_message_remove_tag (message, - argv[remove_tags[i]] + 1); - - for (i = 0; i < add_tags_count; i++) - notmuch_message_add_tag (message, argv[add_tags[i]] + 1); + for (i = 0; tag_ops[i].tag; i++) { + if (tag_ops[i].remove) + notmuch_message_remove_tag (message, tag_ops[i].tag); + else + notmuch_message_add_tag (message, tag_ops[i].tag); + } notmuch_message_thaw (message); diff --git a/test/tagging b/test/tagging index 3acf1bc..e4782ed 100755 --- a/test/tagging +++ b/test/tagging @@ -43,7 +43,7 @@ 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 tag4 unread) +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_done -- cgit v1.2.3 From 5ae960fc192ca1a13469986b567abf98901103de Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Mon, 26 Mar 2012 21:37:15 -0400 Subject: test: Add Emacs test for messages with quotes in their message ID Currently this is broken because Emacs doesn't properly escape double quotes in message IDs. --- test/emacs | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'test') diff --git a/test/emacs b/test/emacs index 8a28705..62eaedb 100755 --- a/test/emacs +++ b/test/emacs @@ -139,6 +139,18 @@ test_emacs '(notmuch-search "id:\"123..456@example\"") 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:" +test_subtest_known_broken +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' \ -- cgit v1.2.3 From ee1180018ee3c772d7ac769222ff9c6940f3c838 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Mon, 26 Mar 2012 21:37:16 -0400 Subject: emacs: Escape all message ID queries This adds a lib function to turn a message ID into a properly escaped message ID query and uses this function wherever we previously hand-constructed ID queries. Wherever this new function is used, documentation has been clarified to refer to "id: queries" instead of "message IDs". This fixes the broken test introduced by the previous patch. --- emacs/notmuch-lib.el | 6 +++++- emacs/notmuch-message.el | 2 +- emacs/notmuch-show.el | 14 +++++++------- test/emacs | 1 - 4 files changed, 13 insertions(+), 10 deletions(-) (limited to 'test') diff --git a/emacs/notmuch-lib.el b/emacs/notmuch-lib.el index a754de7..2492b80 100644 --- a/emacs/notmuch-lib.el +++ b/emacs/notmuch-lib.el @@ -144,6 +144,10 @@ the user hasn't set this variable with the old or new value." "[No Subject]" subject))) +(defun notmuch-id-to-query (id) + "Return a query that matches the message with id ID." + (concat "id:\"" (replace-regexp-in-string "\"" "\"\"" id t t) "\"")) + ;; (defun notmuch-common-do-stash (text) @@ -231,7 +235,7 @@ the given type." (defun notmuch-get-bodypart-content (msg part nth process-crypto) (or (plist-get part :content) - (notmuch-get-bodypart-internal (concat "id:" (plist-get msg :id)) nth process-crypto))) + (notmuch-get-bodypart-internal (notmuch-id-to-query (plist-get msg :id)) nth process-crypto))) (defun notmuch-plist-to-alist (plist) (loop for (key value . rest) on plist by #'cddr diff --git a/emacs/notmuch-message.el b/emacs/notmuch-message.el index 264a5b9..3010281 100644 --- a/emacs/notmuch-message.el +++ b/emacs/notmuch-message.el @@ -44,7 +44,7 @@ the \"inbox\" and \"todo\", you would set (concat "+" str) str)) notmuch-message-replied-tags))) - (apply 'notmuch-tag (concat "id:" (car (car rep))) tags))))) + (apply 'notmuch-tag (notmuch-id-to-query (car (car rep))) tags))))) (add-hook 'message-send-hook 'notmuch-message-mark-replied) diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index 0cd7d82..6d3fe62 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -613,7 +613,7 @@ current buffer, if possible." ;; times (hundreds!), which results in many calls to ;; `notmuch part'. (unless content - (setq content (notmuch-get-bodypart-internal (concat "id:" message-id) + (setq content (notmuch-get-bodypart-internal (notmuch-id-to-query message-id) part-number notmuch-show-process-crypto)) (with-current-buffer w3m-current-buffer (notmuch-show-w3m-cid-store-internal url @@ -1325,16 +1325,16 @@ Some useful entries are: (plist-get props prop))) (defun notmuch-show-get-message-id (&optional bare) - "Return the Message-Id of the current message. + "Return an id: query for the Message-Id of the current message. If optional argument BARE is non-nil, return -the Message-Id without prefix and quotes." +the Message-Id without id: prefix and escaping." (if bare (notmuch-show-get-prop :id) - (concat "id:\"" (notmuch-show-get-prop :id) "\""))) + (notmuch-id-to-query (notmuch-show-get-prop :id)))) (defun notmuch-show-get-messages-ids () - "Return all message ids of messages in the current thread." + "Return all id: queries of messages in the current thread." (let ((message-ids)) (notmuch-show-mapc (lambda () (push (notmuch-show-get-message-id) message-ids))) @@ -1401,7 +1401,7 @@ current thread." ;; thread. (defun notmuch-show-get-message-ids-for-open-messages () - "Return a list of all message IDs for open messages in the current thread." + "Return a list of all id: queries for open messages in the current thread." (save-excursion (let (message-ids done) (goto-char (point-min)) @@ -1805,7 +1805,7 @@ thread from search." (notmuch-common-do-stash (notmuch-show-get-from))) (defun notmuch-show-stash-message-id () - "Copy message ID of current message to kill-ring." + "Copy id: query matching the current message to kill-ring." (interactive) (notmuch-common-do-stash (notmuch-show-get-message-id))) diff --git a/test/emacs b/test/emacs index 62eaedb..8b92d0a 100755 --- a/test/emacs +++ b/test/emacs @@ -140,7 +140,6 @@ 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:" -test_subtest_known_broken add_message '[id]="\"quote\"@example"' '[subject]="Message with quote in Message-Id"' test_emacs '(notmuch-search "subject:\"Message with quote\"") (notmuch-test-wait) -- cgit v1.2.3 From b45b72aa14394ba346a958da7a74303951b41ed4 Mon Sep 17 00:00:00 2001 From: Adam Wolfe Gordon Date: Sun, 1 Apr 2012 09:24:20 -0600 Subject: test: Tests for reply from alternate addresses in emacs Since the recent reply changes were pushed, there has been a bug that causes emacs to always reply from the primary address, even if the JSON or default CLI reply output uses an alternate address. This adds two tests to the emacs test library based on the two "Reply form..." tests in the reply test library. One is currently marked broken. --- test/emacs | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) (limited to 'test') diff --git a/test/emacs b/test/emacs index 8b92d0a..576bc1f 100755 --- a/test/emacs +++ b/test/emacs @@ -285,6 +285,50 @@ Notmuch Test Suite writes: EOF test_expect_equal_file OUTPUT EXPECTED +test_begin_subtest "Reply from alternate address within emacs" +test_subtest_known_broken +add_message '[from]="Sender "' \ + [to]=test_suite_other@notmuchmail.org + +test_emacs "(notmuch-search \"id:\\\"${gen_msg_id}\\\"\") + (notmuch-test-wait) + (notmuch-search-reply-to-thread) + (test-output)" +cat <EXPECTED +From: Notmuch Test Suite +To: Sender +Subject: Re: ${test_subtest_name} +In-Reply-To: <${gen_msg_id}> +Fcc: ${MAIL_DIR}/sent +--text follows this line-- +Sender 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 "' \ + '[to]=group:test_suite@notmuchmail.org,someone@example.com\;' \ + [cc]=test_suite_other@notmuchmail.org + +test_emacs "(notmuch-search \"id:\\\"${gen_msg_id}\\\"\") + (notmuch-test-wait) + (notmuch-search-reply-to-thread) + (test-output)" +cat <EXPECTED +From: Notmuch Test Suite +To: Sender , someone@example.com +Subject: Re: ${test_subtest_name} +In-Reply-To: <${gen_msg_id}> +Fcc: ${MAIL_DIR}/sent +--text follows this line-- +Sender 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 '(notmuch-show "id:20091118002059.067214ed@hikari") (notmuch-show-reply) -- cgit v1.2.3 From 3737ca6e268e6f45353bfbcc4ac4b1d548c5908d Mon Sep 17 00:00:00 2001 From: Adam Wolfe Gordon Date: Sun, 1 Apr 2012 09:24:21 -0600 Subject: emacs: Fix two bugs in reply Bug 1: Replying from alternate addresses ---------------------------------------- The reply code was inconsistent in its use of symbols and strings for header names being passed to message.el functions. This caused the From header to be lookup up incorrectly, causing an additional From header to be added with the user's primary address instead of the correct alternate address. This is fixed by using symbols everywhere, i.e. never using strings for header names when interacting with message.el. This change also removes our use of `mail-header`, since we don't use it anywhere else, and using assq makes it clear how the header lists are expected to work. Bug 2: Duplicate headers in emacs 23.2 -------------------------------------- The message.el code in emacs 23.2 assumes that header names will always be passed as symbols, so our use of strings caused problems. The symptom was that on 23.2 (and presumably on earlier versions) the reply message would end up with two of some headers. Converting everything to symbols also fixes this issue. --- emacs/notmuch-lib.el | 7 +++++-- emacs/notmuch-mua.el | 10 +++++----- test/emacs | 1 - 3 files changed, 10 insertions(+), 8 deletions(-) (limited to 'test') diff --git a/emacs/notmuch-lib.el b/emacs/notmuch-lib.el index c159dda..6907a5f 100644 --- a/emacs/notmuch-lib.el +++ b/emacs/notmuch-lib.el @@ -237,9 +237,12 @@ the given type." (or (plist-get part :content) (notmuch-get-bodypart-internal (notmuch-id-to-query (plist-get msg :id)) nth process-crypto))) -(defun notmuch-plist-to-alist (plist) +;; Converts a plist of headers to an alist of headers. The input plist should +;; have symbols of the form :Header as keys, and the resulting alist will have +;; symbols of the form 'Header as keys. +(defun notmuch-headers-plist-to-alist (plist) (loop for (key value . rest) on plist by #'cddr - collect (cons (substring (symbol-name key) 1) value))) + collect (cons (intern (substring (symbol-name key) 1)) value))) ;; Compatibility functions for versions of emacs before emacs 23. ;; diff --git a/emacs/notmuch-mua.el b/emacs/notmuch-mua.el index 6aae3a0..cfa3d61 100644 --- a/emacs/notmuch-mua.el +++ b/emacs/notmuch-mua.el @@ -127,7 +127,7 @@ list." ((same-window-regexps '("\\*mail .*"))) (notmuch-mua-mail (plist-get reply-headers :To) (plist-get reply-headers :Subject) - (notmuch-plist-to-alist reply-headers))) + (notmuch-headers-plist-to-alist reply-headers))) ;; Insert the message body - but put it in front of the signature ;; if one is present (goto-char (point-max)) @@ -185,11 +185,11 @@ OTHER-ARGS are passed through to `message-mail'." (when notmuch-mua-user-agent-function (let ((user-agent (funcall notmuch-mua-user-agent-function))) (when (not (string= "" user-agent)) - (push (cons "User-Agent" user-agent) other-headers)))) + (push (cons 'User-Agent user-agent) other-headers)))) - (unless (mail-header 'From other-headers) - (push (cons "From" (concat - (notmuch-user-name) " <" (notmuch-user-primary-email) ">")) other-headers)) + (unless (assq 'From other-headers) + (push (cons 'From (concat + (notmuch-user-name) " <" (notmuch-user-primary-email) ">")) other-headers)) (apply #'message-mail to subject other-headers other-args) (message-sort-headers) diff --git a/test/emacs b/test/emacs index 576bc1f..30654bb 100755 --- a/test/emacs +++ b/test/emacs @@ -286,7 +286,6 @@ EOF test_expect_equal_file OUTPUT EXPECTED test_begin_subtest "Reply from alternate address within emacs" -test_subtest_known_broken add_message '[from]="Sender "' \ [to]=test_suite_other@notmuchmail.org -- cgit v1.2.3 From bc531924e0463719d7572ed324edb002cfc1c70f Mon Sep 17 00:00:00 2001 From: Adam Wolfe Gordon Date: Sun, 1 Apr 2012 09:24:22 -0600 Subject: test: Show all headers in emacs reply tests By default, emacs hides the User-Agent and References headers when composing mail. This is a good thing for users, but a bad thing for testing, since we can create ugly or invalid headers and not have it show up in the tests. By setting message-hidden-headers to an empty list, we force emacs to show all the headers, so we can check that they're correct. Users won't see this, but it will let us catch future bugs. As a side-effect, this breaks all the reply tests, since there is a bug with the References and User-Agent headers, fixed in the next commit. --- test/emacs | 55 +++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 43 insertions(+), 12 deletions(-) (limited to 'test') diff --git a/test/emacs b/test/emacs index 30654bb..15cc778 100755 --- a/test/emacs +++ b/test/emacs @@ -267,17 +267,23 @@ EOF test_expect_equal_file OUTPUT EXPECTED test_begin_subtest "Reply within emacs" -test_emacs '(notmuch-search "subject:\"testing message sent via SMTP\"") +test_subtest_known_broken +test_emacs '(let ((message-hidden-headers ''())) + (notmuch-search "subject:\"testing message sent via SMTP\"") (notmuch-test-wait) (notmuch-search-reply-to-thread) - (test-output)' + (test-output))' sed -i -e 's/^In-Reply-To: <.*>$/In-Reply-To: /' OUTPUT +sed -i -e 's/^References: <.*>$/References: /' OUTPUT +sed -i -e 's,^User-Agent: Notmuch/.* Emacs/.*,User-Agent: Notmuch/XXX Emacs/XXX,' OUTPUT cat <EXPECTED From: Notmuch Test Suite To: user@example.com Subject: Re: Testing message sent via SMTP In-Reply-To: Fcc: ${MAIL_DIR}/sent +References: +User-Agent: Notmuch/XXX Emacs/XXX --text follows this line-- Notmuch Test Suite writes: @@ -286,19 +292,24 @@ EOF test_expect_equal_file OUTPUT EXPECTED test_begin_subtest "Reply from alternate address within emacs" +test_subtest_known_broken add_message '[from]="Sender "' \ [to]=test_suite_other@notmuchmail.org -test_emacs "(notmuch-search \"id:\\\"${gen_msg_id}\\\"\") +test_emacs "(let ((message-hidden-headers '())) + (notmuch-search \"id:\\\"${gen_msg_id}\\\"\") (notmuch-test-wait) (notmuch-search-reply-to-thread) - (test-output)" + (test-output))" +sed -i -e 's,^User-Agent: Notmuch/.* Emacs/.*,User-Agent: Notmuch/XXX Emacs/XXX,' OUTPUT cat <EXPECTED From: Notmuch Test Suite To: Sender 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 writes: @@ -307,20 +318,25 @@ EOF test_expect_equal_file OUTPUT EXPECTED test_begin_subtest "Reply from address in named group list within emacs" +test_subtest_known_broken add_message '[from]="Sender "' \ '[to]=group:test_suite@notmuchmail.org,someone@example.com\;' \ [cc]=test_suite_other@notmuchmail.org -test_emacs "(notmuch-search \"id:\\\"${gen_msg_id}\\\"\") +test_emacs "(let ((message-hidden-headers '())) + (notmuch-search \"id:\\\"${gen_msg_id}\\\"\") (notmuch-test-wait) (notmuch-search-reply-to-thread) - (test-output)" + (test-output))" +sed -i -e 's,^User-Agent: Notmuch/.* Emacs/.*,User-Agent: Notmuch/XXX Emacs/XXX,' OUTPUT cat <EXPECTED From: Notmuch Test Suite To: Sender , 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 writes: @@ -329,15 +345,20 @@ EOF test_expect_equal_file OUTPUT EXPECTED test_begin_subtest "Reply within emacs to a multipart/mixed message" -test_emacs '(notmuch-show "id:20091118002059.067214ed@hikari") +test_subtest_known_broken +test_emacs '(let ((message-hidden-headers ''())) + (notmuch-show "id:20091118002059.067214ed@hikari") (notmuch-show-reply) - (test-output)' + (test-output))' +sed -i -e 's,^User-Agent: Notmuch/.* Emacs/.*,User-Agent: Notmuch/XXX Emacs/XXX,' OUTPUT cat <EXPECTED From: Notmuch Test Suite To: Adrian Perez de Castro , 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 writes: @@ -388,15 +409,20 @@ EOF test_expect_equal_file OUTPUT EXPECTED test_begin_subtest "Reply within emacs to a multipart/alternative message" -test_emacs '(notmuch-show "id:cf0c4d610911171136h1713aa59w9cf9aa31f052ad0a@mail.gmail.com") +test_subtest_known_broken +test_emacs '(let ((message-hidden-headers ''())) + (notmuch-show "id:cf0c4d610911171136h1713aa59w9cf9aa31f052ad0a@mail.gmail.com") (notmuch-show-reply) - (test-output)' + (test-output))' +sed -i -e 's,^User-Agent: Notmuch/.* Emacs/.*,User-Agent: Notmuch/XXX Emacs/XXX,' OUTPUT cat <EXPECTED From: Notmuch Test Suite To: Alex Botero-Lowry , notmuch@notmuchmail.org Subject: Re: [notmuch] preliminary FreeBSD support In-Reply-To: Fcc: ${MAIL_DIR}/sent +References: +User-Agent: Notmuch/XXX Emacs/XXX --text follows this line-- Alex Botero-Lowry writes: @@ -424,19 +450,24 @@ EOF test_expect_equal_file OUTPUT EXPECTED test_begin_subtest "Quote MML tags in reply" +test_subtest_known_broken message_id='test-emacs-mml-quoting@message.id' add_message [id]="$message_id" \ "[subject]='$test_subtest_name'" \ '[body]="<#part disposition=inline>"' -test_emacs "(notmuch-show \"id:$message_id\") +test_emacs "(let ((message-hidden-headers '())) + (notmuch-show \"id:$message_id\") (notmuch-show-reply) - (test-output)" + (test-output))" +sed -i -e 's,^User-Agent: Notmuch/.* Emacs/.*,User-Agent: Notmuch/XXX Emacs/XXX,' OUTPUT cat <EXPECTED From: Notmuch Test Suite To: Subject: Re: Quote MML tags in reply In-Reply-To: Fcc: ${MAIL_DIR}/sent +References: +User-Agent: Notmuch/XXX Emacs/XXX --text follows this line-- Notmuch Test Suite writes: -- cgit v1.2.3 From e4844fafec0dd789fe304b412c76f594850b833e Mon Sep 17 00:00:00 2001 From: Adam Wolfe Gordon Date: Sun, 1 Apr 2012 09:24:23 -0600 Subject: emacs: Fix the References header in reply In the new reply code, the References header gets inserted by message.el using a function called message-shorten-references. Unlike all the other header-inserting functions, it doesn't put a newline after the header, causing the next header to end up on the same line. In our case, this header happened to be User-Agent, so it's hard to notice. This is probably a bug in message.el, but we need to work around it. This fixes the problem by wrapping message-shorten-references in a function that inserts a newline after if necessary. This should protect against the message.el bug being fixed in the future. --- emacs/notmuch-mua.el | 28 +++++++++++++++++++++++++--- test/emacs | 6 ------ 2 files changed, 25 insertions(+), 9 deletions(-) (limited to 'test') diff --git a/emacs/notmuch-mua.el b/emacs/notmuch-mua.el index cfa3d61..87bd88d 100644 --- a/emacs/notmuch-mua.el +++ b/emacs/notmuch-mua.el @@ -90,6 +90,15 @@ list." else if (notmuch-match-content-type (plist-get part :content-type) "text/*") collect part)) +;; There is a bug in emacs 23's message.el that results in a newline +;; not being inserted after the References header, so the next header +;; is concatenated to the end of it. This function fixes the problem, +;; while guarding against the possibility that some current or future +;; version of emacs has the bug fixed. +(defun notmuch-mua-insert-references (original-func header references) + (funcall original-func header references) + (unless (bolp) (insert "\n"))) + (defun notmuch-mua-reply (query-string &optional sender reply-all) (let ((args '("reply" "--format=json")) reply @@ -125,9 +134,22 @@ list." ;; Overlay the composition window on that being used to read ;; the original message. ((same-window-regexps '("\\*mail .*"))) - (notmuch-mua-mail (plist-get reply-headers :To) - (plist-get reply-headers :Subject) - (notmuch-headers-plist-to-alist reply-headers))) + + ;; We modify message-header-format-alist to get around a bug in message.el. + ;; See the comment above on notmuch-mua-insert-references. + (let ((message-header-format-alist + (loop for pair in message-header-format-alist + if (eq (car pair) 'References) + collect (cons 'References + (apply-partially + 'notmuch-mua-insert-references + (cdr pair))) + else + collect pair))) + (notmuch-mua-mail (plist-get reply-headers :To) + (plist-get reply-headers :Subject) + (notmuch-headers-plist-to-alist reply-headers)))) + ;; Insert the message body - but put it in front of the signature ;; if one is present (goto-char (point-max)) diff --git a/test/emacs b/test/emacs index 15cc778..c7510e9 100755 --- a/test/emacs +++ b/test/emacs @@ -267,7 +267,6 @@ EOF test_expect_equal_file OUTPUT EXPECTED test_begin_subtest "Reply within emacs" -test_subtest_known_broken test_emacs '(let ((message-hidden-headers ''())) (notmuch-search "subject:\"testing message sent via SMTP\"") (notmuch-test-wait) @@ -292,7 +291,6 @@ EOF test_expect_equal_file OUTPUT EXPECTED test_begin_subtest "Reply from alternate address within emacs" -test_subtest_known_broken add_message '[from]="Sender "' \ [to]=test_suite_other@notmuchmail.org @@ -318,7 +316,6 @@ EOF test_expect_equal_file OUTPUT EXPECTED test_begin_subtest "Reply from address in named group list within emacs" -test_subtest_known_broken add_message '[from]="Sender "' \ '[to]=group:test_suite@notmuchmail.org,someone@example.com\;' \ [cc]=test_suite_other@notmuchmail.org @@ -345,7 +342,6 @@ EOF test_expect_equal_file OUTPUT EXPECTED test_begin_subtest "Reply within emacs to a multipart/mixed message" -test_subtest_known_broken test_emacs '(let ((message-hidden-headers ''())) (notmuch-show "id:20091118002059.067214ed@hikari") (notmuch-show-reply) @@ -409,7 +405,6 @@ EOF test_expect_equal_file OUTPUT EXPECTED test_begin_subtest "Reply within emacs to a multipart/alternative message" -test_subtest_known_broken test_emacs '(let ((message-hidden-headers ''())) (notmuch-show "id:cf0c4d610911171136h1713aa59w9cf9aa31f052ad0a@mail.gmail.com") (notmuch-show-reply) @@ -450,7 +445,6 @@ EOF test_expect_equal_file OUTPUT EXPECTED test_begin_subtest "Quote MML tags in reply" -test_subtest_known_broken message_id='test-emacs-mml-quoting@message.id' add_message [id]="$message_id" \ "[subject]='$test_subtest_name'" \ -- cgit v1.2.3 From 818790f7b52fbab06b9536e4d90c6142cadfcd5f Mon Sep 17 00:00:00 2001 From: Dmitry Kurochkin Date: Fri, 9 Mar 2012 11:34:52 +0400 Subject: test: add broken test for long names in Emacs notmuch-hello view Currently, the column alignment in Emacs notmuch-hello is broken for tags/queries with long names. --- test/emacs-hello | 9 +++++++++ test/emacs.expected-output/notmuch-hello-long-names | 18 ++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 test/emacs.expected-output/notmuch-hello-long-names (limited to 'test') diff --git a/test/emacs-hello b/test/emacs-hello index b235e3a..9e5d045 100755 --- a/test/emacs-hello +++ b/test/emacs-hello @@ -44,4 +44,13 @@ test_emacs "(let ((notmuch-hello-sections (test-output))" test_expect_equal_file OUTPUT $EXPECTED/notmuch-hello-section-counts +test_begin_subtest "Column alignment for tag/queries with long names" +test_subtest_known_broken +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 diff --git a/test/emacs.expected-output/notmuch-hello-long-names b/test/emacs.expected-output/notmuch-hello-long-names new file mode 100644 index 0000000..be6d2c5 --- /dev/null +++ b/test/emacs.expected-output/notmuch-hello-long-names @@ -0,0 +1,18 @@ + Welcome to notmuch. You have 52 messages. + +Saved searches: [edit] + + 52 inbox 52 unread + +Search: . + +All tags: [hide] + + 52 a-very-long-tag 52 inbox 52 unread + 4 attachment 7 signed + + Type a search query and hit RET to view matching threads. + Edit saved searches with the `edit' button. + Hit RET or click on a saved search or tag name to view matching threads. + `=' to refresh this screen. `s' to search messages. `q' to quit. + Customize this page. -- cgit v1.2.3 From 1361dd37bc758c84ab32f629d04327231954c60b Mon Sep 17 00:00:00 2001 From: Dmitry Kurochkin Date: Fri, 9 Mar 2012 11:34:53 +0400 Subject: emacs: fix off-by-one error in notmuch-hello column alignment Expected results for few tests are fixed, the relevant test is unmarked broken. --- emacs/notmuch-hello.el | 2 +- test/emacs-hello | 1 - test/emacs.expected-output/notmuch-hello-new-section | 2 +- test/emacs.expected-output/notmuch-hello-section-with-empty | 2 +- 4 files changed, 3 insertions(+), 4 deletions(-) (limited to 'test') diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el index e9caade..28f39f1 100644 --- a/emacs/notmuch-hello.el +++ b/emacs/notmuch-hello.el @@ -461,7 +461,7 @@ Such a list can be computed with `notmuch-hello-query-counts'." ;; just insert `(- widest (length name))' spaces - the ;; column separator is included in the button if ;; `(equal widest (length name)'. - (widget-insert (make-string (max 1 + (widget-insert (make-string (max 0 (- widest (length name))) ? ))))) (setq count (1+ count)) diff --git a/test/emacs-hello b/test/emacs-hello index 9e5d045..be66ba4 100755 --- a/test/emacs-hello +++ b/test/emacs-hello @@ -45,7 +45,6 @@ test_emacs "(let ((notmuch-hello-sections test_expect_equal_file OUTPUT $EXPECTED/notmuch-hello-section-counts test_begin_subtest "Column alignment for tag/queries with long names" -test_subtest_known_broken tag=a-very-long-tag # length carefully calculated for 80 characters window width notmuch tag +$tag '*' test_emacs '(notmuch-hello) diff --git a/test/emacs.expected-output/notmuch-hello-new-section b/test/emacs.expected-output/notmuch-hello-new-section index c64d712..6a339aa 100644 --- a/test/emacs.expected-output/notmuch-hello-new-section +++ b/test/emacs.expected-output/notmuch-hello-new-section @@ -1,4 +1,4 @@ Test: [hide] - 52 inbox + 52 inbox diff --git a/test/emacs.expected-output/notmuch-hello-section-with-empty b/test/emacs.expected-output/notmuch-hello-section-with-empty index 8209fed..dc2568d 100644 --- a/test/emacs.expected-output/notmuch-hello-section-with-empty +++ b/test/emacs.expected-output/notmuch-hello-section-with-empty @@ -1,4 +1,4 @@ Test-with-empty: [hide] - 52 inbox + 52 inbox -- cgit v1.2.3 From 785c1e497f05cb89365669fea33cfbf9078a4b12 Mon Sep 17 00:00:00 2001 From: Mark Walters Date: Sat, 7 Apr 2012 17:10:04 +0100 Subject: cli: move count to the new --exclude=(true|false|flag) naming scheme. Move the option --no-exclude to the --exclude= scheme. Since there is no way to flag messages only true and false are implemented. Note that, for consistency with other commands, this is implemented as a keyword option rather than a boolean option. --- man/man1/notmuch-count.1 | 5 +++-- notmuch-count.c | 17 ++++++++++++----- test/count | 4 ++-- 3 files changed, 17 insertions(+), 9 deletions(-) (limited to 'test') diff --git a/man/man1/notmuch-count.1 b/man/man1/notmuch-count.1 index 35ecc53..d6cbf07 100644 --- a/man/man1/notmuch-count.1 +++ b/man/man1/notmuch-count.1 @@ -41,9 +41,10 @@ Output the number of matching threads. .RS 4 .TP 4 -.BR \-\-no\-exclude +.BR \-\-exclude=(true|false) -Do not exclude the messages matching search.exclude_tags in the config file. +Specify whether to omit messages matching search.tag_exclude from the +count (the default) or not. .RE .RE .RE diff --git a/notmuch-count.c b/notmuch-count.c index 46b76ae..b76690c 100644 --- a/notmuch-count.c +++ b/notmuch-count.c @@ -26,6 +26,12 @@ enum { OUTPUT_MESSAGES, }; +/* The following is to allow future options to be added more easily */ +enum { + EXCLUDE_TRUE, + EXCLUDE_FALSE, +}; + int notmuch_count_command (void *ctx, int argc, char *argv[]) { @@ -35,7 +41,7 @@ notmuch_count_command (void *ctx, int argc, char *argv[]) char *query_str; int opt_index; int output = OUTPUT_MESSAGES; - notmuch_bool_t no_exclude = FALSE; + int exclude = EXCLUDE_TRUE; unsigned int i; notmuch_opt_desc_t options[] = { @@ -43,7 +49,10 @@ notmuch_count_command (void *ctx, int argc, char *argv[]) (notmuch_keyword_t []){ { "threads", OUTPUT_THREADS }, { "messages", OUTPUT_MESSAGES }, { 0, 0 } } }, - { NOTMUCH_OPT_BOOLEAN, &no_exclude, "no-exclude", 'd', 0 }, + { NOTMUCH_OPT_KEYWORD, &exclude, "exclude", 'x', + (notmuch_keyword_t []){ { "true", EXCLUDE_TRUE }, + { "false", EXCLUDE_FALSE }, + { 0, 0 } } }, { 0, 0, 0, 0, 0 } }; @@ -78,7 +87,7 @@ notmuch_count_command (void *ctx, int argc, char *argv[]) return 1; } - if (!no_exclude) { + if (exclude == EXCLUDE_TRUE) { const char **search_exclude_tags; size_t search_exclude_tags_length; @@ -88,8 +97,6 @@ notmuch_count_command (void *ctx, int argc, char *argv[]) notmuch_query_add_tag_exclude (query, search_exclude_tags[i]); } - notmuch_query_set_omit_excluded_messages (query, TRUE); - switch (output) { case OUTPUT_MESSAGES: printf ("%u\n", notmuch_query_count_messages (query)); diff --git a/test/count b/test/count index b97fc06..fd387e5 100755 --- a/test/count +++ b/test/count @@ -53,9 +53,9 @@ test_expect_equal \ "1" \ "`notmuch count subject:deleted and tag:deleted`" -test_begin_subtest "count \"deleted\" messages, with --no-exclude" +test_begin_subtest "count \"deleted\" messages, --exclude=false" test_expect_equal \ "3" \ - "`notmuch count --no-exclude subject:deleted`" + "`notmuch count --exclude=false subject:deleted`" test_done -- cgit v1.2.3 From 6478e1bc92d60bfd85ef8259a14754e2babe150b Mon Sep 17 00:00:00 2001 From: Mark Walters Date: Sat, 7 Apr 2012 17:10:07 +0100 Subject: test: add some exclude tests Systematically test the exclude options for search. Also move the search existing exclude tests into the new test. There is some overlap between the two sets of tests but many of the existing ones are there because they triggered bugs in the past so I have kept them to ensure coverage. --- test/count | 21 --- test/excludes | 423 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ test/notmuch-test | 1 + test/search | 48 ------- 4 files changed, 424 insertions(+), 69 deletions(-) create mode 100755 test/excludes (limited to 'test') diff --git a/test/count b/test/count index fd387e5..300b171 100755 --- a/test/count +++ b/test/count @@ -37,25 +37,4 @@ test_expect_equal \ "0" \ "`notmuch count --output=threads ${SEARCH}`" -test_begin_subtest "count excluding \"deleted\" messages" -notmuch config set search.exclude_tags deleted -generate_message '[subject]="Not deleted"' -generate_message '[subject]="Another not deleted"' -generate_message '[subject]="Deleted"' -notmuch new > /dev/null -notmuch tag +deleted id:$gen_msg_id -test_expect_equal \ - "2" \ - "`notmuch count subject:deleted`" - -test_begin_subtest "count \"deleted\" messages, exclude overridden" -test_expect_equal \ - "1" \ - "`notmuch count subject:deleted and tag:deleted`" - -test_begin_subtest "count \"deleted\" messages, --exclude=false" -test_expect_equal \ - "3" \ - "`notmuch count --exclude=false subject:deleted`" - test_done diff --git a/test/excludes b/test/excludes new file mode 100755 index 0000000..24d653e --- /dev/null +++ b/test/excludes @@ -0,0 +1,423 @@ +#!/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; Not deleted reply (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 4 (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, 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]}" + + +######################################################### +# 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" " message{ id:XXXXX depth:0 match:1 excluded:0 filename:XXXXX +Subject: Some messages excluded: single non-excluded match: reply 4 + message{ 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" " message{ id:XXXXX depth:0 match:0 excluded:0 filename:XXXXX +Subject: Some messages excluded: single non-excluded match: top message + message{ id:XXXXX depth:1 match:0 excluded:0 filename:XXXXX +Subject: Some messages excluded: single non-excluded match: reply 1 + message{ id:XXXXX depth:2 match:0 excluded:1 filename:XXXXX +Subject: Some messages excluded: single non-excluded match: reply 2 + message{ id:XXXXX depth:3 match:0 excluded:0 filename:XXXXX +Subject: Some messages excluded: single non-excluded match: reply 3 + message{ id:XXXXX depth:4 match:1 excluded:0 filename:XXXXX +Subject: Some messages excluded: single non-excluded match: reply 4 + message{ id:XXXXX depth:5 match:0 excluded:0 filename:XXXXX +Subject: Some messages excluded: single non-excluded match: reply 5 + message{ id:XXXXX depth:0 match:0 excluded:0 filename:XXXXX +Subject: No messages excluded: single match: top message + message{ id:XXXXX depth:1 match:0 excluded:0 filename:XXXXX +Subject: No messages excluded: single match: reply 1 + message{ id:XXXXX depth:2 match:0 excluded:0 filename:XXXXX +Subject: No messages excluded: single match: reply 2 + message{ id:XXXXX depth:3 match:1 excluded:0 filename:XXXXX +Subject: No messages excluded: single match: reply 3 + message{ id:XXXXX depth:4 match:0 excluded:0 filename:XXXXX +Subject: No messages excluded: single match: reply 4 + message{ 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" " message{ id:XXXXX depth:0 match:1 excluded:0 filename:XXXXX +Subject: Some messages excluded: single non-excluded match: reply 4 + message{ 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" " message{ id:XXXXX depth:0 match:0 excluded:0 filename:XXXXX +Subject: Some messages excluded: single non-excluded match: top message + message{ id:XXXXX depth:1 match:0 excluded:0 filename:XXXXX +Subject: Some messages excluded: single non-excluded match: reply 1 + message{ id:XXXXX depth:2 match:0 excluded:1 filename:XXXXX +Subject: Some messages excluded: single non-excluded match: reply 2 + message{ id:XXXXX depth:3 match:0 excluded:0 filename:XXXXX +Subject: Some messages excluded: single non-excluded match: reply 3 + message{ id:XXXXX depth:4 match:1 excluded:0 filename:XXXXX +Subject: Some messages excluded: single non-excluded match: reply 4 + message{ id:XXXXX depth:5 match:0 excluded:0 filename:XXXXX +Subject: Some messages excluded: single non-excluded match: reply 5 + message{ id:XXXXX depth:0 match:0 excluded:0 filename:XXXXX +Subject: No messages excluded: single match: top message + message{ id:XXXXX depth:1 match:0 excluded:0 filename:XXXXX +Subject: No messages excluded: single match: reply 1 + message{ id:XXXXX depth:2 match:0 excluded:0 filename:XXXXX +Subject: No messages excluded: single match: reply 2 + message{ id:XXXXX depth:3 match:1 excluded:0 filename:XXXXX +Subject: No messages excluded: single match: reply 3 + message{ id:XXXXX depth:4 match:0 excluded:0 filename:XXXXX +Subject: No messages excluded: single match: reply 4 + message{ 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" " message{ id:XXXXX depth:0 match:1 excluded:1 filename:XXXXX +Subject: All messages excluded: single match: reply 2 + message{ id:XXXXX depth:0 match:1 excluded:1 filename:XXXXX +Subject: All messages excluded: double match: reply 2 + message{ id:XXXXX depth:1 match:1 excluded:1 filename:XXXXX +Subject: All messages excluded: double match: reply 4 + message{ id:XXXXX depth:0 match:1 excluded:1 filename:XXXXX +Subject: Some messages excluded: single excluded match: reply 3 + message{ id:XXXXX depth:0 match:1 excluded:0 filename:XXXXX +Subject: Some messages excluded: single non-excluded match: reply 4 + message{ 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" " message{ id:XXXXX depth:0 match:0 excluded:1 filename:XXXXX +Subject: All messages excluded: single match: top message + message{ id:XXXXX depth:1 match:0 excluded:1 filename:XXXXX +Subject: All messages excluded: single match: reply 1 + message{ id:XXXXX depth:2 match:1 excluded:1 filename:XXXXX +Subject: All messages excluded: single match: reply 2 + message{ id:XXXXX depth:3 match:0 excluded:1 filename:XXXXX +Subject: All messages excluded: single match: reply 3 + message{ id:XXXXX depth:4 match:0 excluded:1 filename:XXXXX +Subject: All messages excluded: single match: reply 4 + message{ id:XXXXX depth:5 match:0 excluded:1 filename:XXXXX +Subject: All messages excluded: single match: reply 5 + message{ id:XXXXX depth:0 match:0 excluded:1 filename:XXXXX +Subject: All messages excluded: double match: top message + message{ id:XXXXX depth:1 match:0 excluded:1 filename:XXXXX +Subject: All messages excluded: double match: reply 1 + message{ id:XXXXX depth:2 match:1 excluded:1 filename:XXXXX +Subject: All messages excluded: double match: reply 2 + message{ id:XXXXX depth:3 match:0 excluded:1 filename:XXXXX +Subject: All messages excluded: double match: reply 3 + message{ id:XXXXX depth:4 match:1 excluded:1 filename:XXXXX +Subject: All messages excluded: double match: reply 4 + message{ id:XXXXX depth:5 match:0 excluded:1 filename:XXXXX +Subject: All messages excluded: double match: reply 5 + message{ id:XXXXX depth:0 match:0 excluded:0 filename:XXXXX +Subject: Some messages excluded: single excluded match: top message + message{ id:XXXXX depth:1 match:0 excluded:0 filename:XXXXX +Subject: Some messages excluded: single excluded match: reply 1 + message{ id:XXXXX depth:2 match:0 excluded:0 filename:XXXXX +Subject: Some messages excluded: single excluded match: reply 2 + message{ id:XXXXX depth:3 match:1 excluded:1 filename:XXXXX +Subject: Some messages excluded: single excluded match: reply 3 + message{ id:XXXXX depth:4 match:0 excluded:0 filename:XXXXX +Subject: Some messages excluded: single excluded match: reply 4 + message{ id:XXXXX depth:5 match:0 excluded:0 filename:XXXXX +Subject: Some messages excluded: single excluded match: reply 5 + message{ id:XXXXX depth:0 match:0 excluded:0 filename:XXXXX +Subject: Some messages excluded: single non-excluded match: top message + message{ id:XXXXX depth:1 match:0 excluded:0 filename:XXXXX +Subject: Some messages excluded: single non-excluded match: reply 1 + message{ id:XXXXX depth:2 match:0 excluded:1 filename:XXXXX +Subject: Some messages excluded: single non-excluded match: reply 2 + message{ id:XXXXX depth:3 match:0 excluded:0 filename:XXXXX +Subject: Some messages excluded: single non-excluded match: reply 3 + message{ id:XXXXX depth:4 match:1 excluded:0 filename:XXXXX +Subject: Some messages excluded: single non-excluded match: reply 4 + message{ id:XXXXX depth:5 match:0 excluded:0 filename:XXXXX +Subject: Some messages excluded: single non-excluded match: reply 5 + message{ id:XXXXX depth:0 match:0 excluded:0 filename:XXXXX +Subject: No messages excluded: single match: top message + message{ id:XXXXX depth:1 match:0 excluded:0 filename:XXXXX +Subject: No messages excluded: single match: reply 1 + message{ id:XXXXX depth:2 match:0 excluded:0 filename:XXXXX +Subject: No messages excluded: single match: reply 2 + message{ id:XXXXX depth:3 match:1 excluded:0 filename:XXXXX +Subject: No messages excluded: single match: reply 3 + message{ id:XXXXX depth:4 match:0 excluded:0 filename:XXXXX +Subject: No messages excluded: single match: reply 4 + message{ id:XXXXX depth:5 match:0 excluded:0 filename:XXXXX +Subject: No messages excluded: single match: reply 5" + + +test_done diff --git a/test/notmuch-test b/test/notmuch-test index f03b594..801df73 100755 --- a/test/notmuch-test +++ b/test/notmuch-test @@ -27,6 +27,7 @@ TESTS=" search-position-overlap-bug search-insufficient-from-quoting search-limiting + excludes tagging json multipart diff --git a/test/search b/test/search index 17af6a2..a7a0b18 100755 --- a/test/search +++ b/test/search @@ -129,52 +129,4 @@ add_message '[subject]="utf8-message-body-subject"' '[date]="Sat, 01 Jan 2000 12 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_begin_subtest "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) -thread:XXX 2001-01-05 [0/1] Notmuch Test Suite; Deleted (deleted inbox unread)" - -test_begin_subtest "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 "Exclude \"deleted\" messages from message search (no-exclude)" -output=$(notmuch search --no-exclude --output=messages subject:deleted | notmuch_search_sanitize) -test_expect_equal "$output" "id:$not_deleted_id -id:$deleted_id" - -test_begin_subtest "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 "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 "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 "Don't exclude \"deleted\" messages when --no-exclude specified" -output=$(notmuch search --no-exclude 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)" - -test_begin_subtest "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)" - test_done -- cgit v1.2.3 From 6409a27b2c835223806e4b14cc219c927856c256 Mon Sep 17 00:00:00 2001 From: Dmitry Kurochkin Date: Sat, 10 Mar 2012 07:54:15 +0400 Subject: emacs: get rid of trailing spaces in notmuch-hello view This patch removes trailing spaces in notmuch-hello view. A side effect of this change is that tag/query buttons no longer include a space at the end. This means that pressing RET when the point is at the first character after the tag/query button no longer works (note that this is the standard behavior for buttons). We may change this behavior in the future (without adding trailing spaces back) if people would find this change inconvenient. --- emacs/notmuch-hello.el | 30 +++++++++------------- test/emacs | 2 +- test/emacs.expected-output/notmuch-hello | 2 +- .../emacs.expected-output/notmuch-hello-long-names | 6 ++--- .../notmuch-hello-new-section | 2 +- .../notmuch-hello-section-counts | 4 +-- .../notmuch-hello-section-hidden-tag | 2 +- .../notmuch-hello-section-with-empty | 2 +- .../emacs.expected-output/notmuch-hello-with-empty | 2 +- 9 files changed, 23 insertions(+), 29 deletions(-) (limited to 'test') diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el index 6b4b2c1..71d37b8 100644 --- a/emacs/notmuch-hello.el +++ b/emacs/notmuch-hello.el @@ -429,7 +429,8 @@ Such a list can be computed with `notmuch-hello-query-counts'." (let* ((widest (notmuch-hello-longest-label searches)) (tags-and-width (notmuch-hello-tags-per-line widest)) (tags-per-line (car tags-and-width)) - (widest (cdr tags-and-width)) + (column-width (cdr tags-and-width)) + (column-indent 0) (count 0) (reordered-list (notmuch-hello-reflect searches tags-per-line)) ;; Hack the display of the buttons used. @@ -441,32 +442,25 @@ Such a list can be computed with `notmuch-hello-query-counts'." (mapc (lambda (elem) ;; (not elem) indicates an empty slot in the matrix. (when elem + (if (> column-indent 0) + (widget-insert (make-string column-indent ? ))) (let* ((name (first elem)) (query (second elem)) - (msg-count (third elem)) - (formatted-name (format "%s " name))) + (msg-count (third elem))) (widget-insert (format "%8s " (notmuch-hello-nice-number msg-count))) - (if (string= formatted-name notmuch-hello-target) + (if (string= name notmuch-hello-target) (setq found-target-pos (point-marker))) (widget-create 'push-button :notify #'notmuch-hello-widget-search :notmuch-search-terms query - formatted-name) - (unless (eq (% count tags-per-line) (1- tags-per-line)) - ;; If this is not the last tag on the line, insert - ;; enough space to consume the rest of the column. - ;; Because the button for the name is `(1+ (length - ;; name))' long (due to the trailing space) we can - ;; just insert `(- widest (length name))' spaces - the - ;; column separator is included in the button if - ;; `(equal widest (length name)'. - (widget-insert (make-string (max 0 - (- widest (length name))) - ? ))))) + name) + (setq column-indent + (1+ (max 0 (- column-width (length name))))))) (setq count (1+ count)) - (if (eq (% count tags-per-line) 0) - (widget-insert "\n"))) + (when (eq (% count tags-per-line) 0) + (setq column-indent 0) + (widget-insert "\n"))) reordered-list) ;; If the last line was not full (and hence did not include a diff --git a/test/emacs b/test/emacs index c7510e9..38decd0 100755 --- a/test/emacs +++ b/test/emacs @@ -39,7 +39,7 @@ 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 (point)) + (widget-button-press (1- (point))) (notmuch-test-wait) (test-output)' test_expect_equal_file OUTPUT $EXPECTED/notmuch-hello-view-inbox diff --git a/test/emacs.expected-output/notmuch-hello b/test/emacs.expected-output/notmuch-hello index 1470790..2d69891 100644 --- a/test/emacs.expected-output/notmuch-hello +++ b/test/emacs.expected-output/notmuch-hello @@ -2,7 +2,7 @@ Saved searches: [edit] - 52 inbox 52 unread + 52 inbox 52 unread Search: . diff --git a/test/emacs.expected-output/notmuch-hello-long-names b/test/emacs.expected-output/notmuch-hello-long-names index be6d2c5..486d0d9 100644 --- a/test/emacs.expected-output/notmuch-hello-long-names +++ b/test/emacs.expected-output/notmuch-hello-long-names @@ -2,14 +2,14 @@ Saved searches: [edit] - 52 inbox 52 unread + 52 inbox 52 unread Search: . All tags: [hide] - 52 a-very-long-tag 52 inbox 52 unread - 4 attachment 7 signed + 52 a-very-long-tag 52 inbox 52 unread + 4 attachment 7 signed Type a search query and hit RET to view matching threads. Edit saved searches with the `edit' button. diff --git a/test/emacs.expected-output/notmuch-hello-new-section b/test/emacs.expected-output/notmuch-hello-new-section index 6a339aa..67fdef2 100644 --- a/test/emacs.expected-output/notmuch-hello-new-section +++ b/test/emacs.expected-output/notmuch-hello-new-section @@ -1,4 +1,4 @@ Test: [hide] - 52 inbox + 52 inbox diff --git a/test/emacs.expected-output/notmuch-hello-section-counts b/test/emacs.expected-output/notmuch-hello-section-counts index 9d79659..7a9827c 100644 --- a/test/emacs.expected-output/notmuch-hello-section-counts +++ b/test/emacs.expected-output/notmuch-hello-section-counts @@ -1,5 +1,5 @@ Test-with-counts: [hide] - 2 attachment 7 signed - 7 inbox 7 unread + 2 attachment 7 signed + 7 inbox 7 unread diff --git a/test/emacs.expected-output/notmuch-hello-section-hidden-tag b/test/emacs.expected-output/notmuch-hello-section-hidden-tag index 3688e7c..809a114 100644 --- a/test/emacs.expected-output/notmuch-hello-section-hidden-tag +++ b/test/emacs.expected-output/notmuch-hello-section-hidden-tag @@ -1,4 +1,4 @@ Test-with-filtered: [hide] - 4 attachment 52 inbox 7 signed + 4 attachment 52 inbox 7 signed diff --git a/test/emacs.expected-output/notmuch-hello-section-with-empty b/test/emacs.expected-output/notmuch-hello-section-with-empty index dc2568d..5c67317 100644 --- a/test/emacs.expected-output/notmuch-hello-section-with-empty +++ b/test/emacs.expected-output/notmuch-hello-section-with-empty @@ -1,4 +1,4 @@ Test-with-empty: [hide] - 52 inbox + 52 inbox diff --git a/test/emacs.expected-output/notmuch-hello-with-empty b/test/emacs.expected-output/notmuch-hello-with-empty index 5e53222..854e0c2 100644 --- a/test/emacs.expected-output/notmuch-hello-with-empty +++ b/test/emacs.expected-output/notmuch-hello-with-empty @@ -2,7 +2,7 @@ Saved searches: [edit] - 52 inbox 52 unread 0 empty + 52 inbox 52 unread 0 empty Search: . -- cgit v1.2.3 From b8c7707d4d2faeceb2ea2f79255b792a06bbbffe Mon Sep 17 00:00:00 2001 From: Peter Wang Date: Sat, 14 Apr 2012 11:41:03 +1000 Subject: test: Add tests for 'config' command Start a new test script. --- test/config | 45 +++++++++++++++++++++++++++++++++++++++++++++ test/notmuch-test | 1 + 2 files changed, 46 insertions(+) create mode 100755 test/config (limited to 'test') diff --git a/test/config b/test/config new file mode 100755 index 0000000..9030154 --- /dev/null +++ b/test/config @@ -0,0 +1,45 @@ +#!/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_done diff --git a/test/notmuch-test b/test/notmuch-test index 801df73..bfad5d3 100755 --- a/test/notmuch-test +++ b/test/notmuch-test @@ -19,6 +19,7 @@ cd $(dirname "$0") TESTS=" basic help-test + config new count search -- cgit v1.2.3 From 86f01063d74cb45ed83df80c9406262ae533d178 Mon Sep 17 00:00:00 2001 From: Peter Wang Date: Sat, 14 Apr 2012 11:41:04 +1000 Subject: test: Add broken test for 'config list' Proposed functionality. --- test/config | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'test') diff --git a/test/config b/test/config index 9030154..3bf8098 100755 --- a/test/config +++ b/test/config @@ -42,4 +42,20 @@ 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" +test_subtest_known_broken +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_done -- cgit v1.2.3 From d32de8b3c0ba9e3224fbe66e76444bd44c1978fc Mon Sep 17 00:00:00 2001 From: Peter Wang Date: Sat, 14 Apr 2012 11:41:05 +1000 Subject: config: Add 'config list' command Add a command to list all configuration items with their associated values. One use is as follows: a MUA may prefer to store data in a central notmuch configuration file so that the data is accessible across different machines, e.g. an addressbook. The list command helps to implement features such as tab completion on the keys. --- notmuch-config.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ test/config | 1 - 2 files changed, 47 insertions(+), 1 deletion(-) (limited to 'test') diff --git a/notmuch-config.c b/notmuch-config.c index f9eb977..3e37a2d 100644 --- a/notmuch-config.c +++ b/notmuch-config.c @@ -799,6 +799,51 @@ notmuch_config_command_set (void *ctx, char *item, int argc, char *argv[]) return ret; } +static int +notmuch_config_command_list (void *ctx) +{ + notmuch_config_t *config; + char **groups; + size_t g, groups_length; + + config = notmuch_config_open (ctx, NULL, NULL); + if (config == NULL) + return 1; + + groups = g_key_file_get_groups (config->key_file, &groups_length); + if (groups == NULL) + return 1; + + for (g = 0; g < groups_length; g++) { + char **keys; + size_t k, keys_length; + + keys = g_key_file_get_keys (config->key_file, + groups[g], &keys_length, NULL); + if (keys == NULL) + continue; + + for (k = 0; k < keys_length; k++) { + char *value; + + value = g_key_file_get_string (config->key_file, + groups[g], keys[k], NULL); + if (value != NULL) { + printf ("%s.%s=%s\n", groups[g], keys[k], value); + free (value); + } + } + + g_strfreev (keys); + } + + g_strfreev (groups); + + notmuch_config_close (config); + + return 0; +} + int notmuch_config_command (void *ctx, int argc, char *argv[]) { @@ -823,6 +868,8 @@ notmuch_config_command (void *ctx, int argc, char *argv[]) return 1; } return notmuch_config_command_set (ctx, argv[1], argc - 2, argv + 2); + } else if (strcmp (argv[0], "list") == 0) { + return notmuch_config_command_list (ctx); } fprintf (stderr, "Unrecognized argument for notmuch config: %s\n", diff --git a/test/config b/test/config index 3bf8098..93ecb13 100755 --- a/test/config +++ b/test/config @@ -43,7 +43,6 @@ notmuch config set foo.nonexistent test_expect_equal "$(notmuch config get foo.nonexistent)" "" test_begin_subtest "List all items" -test_subtest_known_broken notmuch config set database.path "/canonical/path" output=$(notmuch config list) test_expect_equal "$output" "\ -- cgit v1.2.3 From 5fddc07dc31481453c1af186bf7da241c00cdbf1 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Mon, 30 Apr 2012 12:25:33 -0400 Subject: lib/cli: Make notmuch_database_open return a status code It has been a long-standing issue that notmuch_database_open doesn't return any indication of why it failed. This patch changes its prototype to return a notmuch_status_t and set an out-argument to the database itself, like other functions that return both a status and an object. In the interest of atomicity, this also updates every use in the CLI so that notmuch still compiles. Since this patch does not update the bindings, the Python bindings test fails. --- lib/database.cc | 28 +++++++++++++++++++++++----- lib/notmuch.h | 26 +++++++++++++++++++------- notmuch-count.c | 5 ++--- notmuch-dump.c | 5 ++--- notmuch-new.c | 5 ++--- notmuch-reply.c | 5 ++--- notmuch-restore.c | 5 ++--- notmuch-search.c | 5 ++--- notmuch-show.c | 5 ++--- notmuch-tag.c | 5 ++--- test/symbol-test.cc | 3 ++- 11 files changed, 60 insertions(+), 37 deletions(-) (limited to 'test') diff --git a/lib/database.cc b/lib/database.cc index 2fefcad..1e66599 100644 --- a/lib/database.cc +++ b/lib/database.cc @@ -556,8 +556,9 @@ notmuch_database_create (const char *path) goto DONE; } - notmuch = notmuch_database_open (path, - NOTMUCH_DATABASE_MODE_READ_WRITE); + notmuch_database_open (path, + NOTMUCH_DATABASE_MODE_READ_WRITE, + ¬much); notmuch_database_upgrade (notmuch, NULL, NULL); DONE: @@ -578,10 +579,12 @@ _notmuch_database_ensure_writable (notmuch_database_t *notmuch) return NOTMUCH_STATUS_SUCCESS; } -notmuch_database_t * +notmuch_status_t notmuch_database_open (const char *path, - notmuch_database_mode_t mode) + notmuch_database_mode_t mode, + notmuch_database_t **database) { + notmuch_status_t status = NOTMUCH_STATUS_SUCCESS; void *local = talloc_new (NULL); notmuch_database_t *notmuch = NULL; char *notmuch_path, *xapian_path; @@ -590,8 +593,15 @@ notmuch_database_open (const char *path, unsigned int i, version; static int initialized = 0; + if (path == NULL) { + fprintf (stderr, "Error: Cannot open a database for a NULL path.\n"); + status = NOTMUCH_STATUS_NULL_POINTER; + goto DONE; + } + if (! (notmuch_path = talloc_asprintf (local, "%s/%s", path, ".notmuch"))) { fprintf (stderr, "Out of memory\n"); + status = NOTMUCH_STATUS_OUT_OF_MEMORY; goto DONE; } @@ -599,11 +609,13 @@ notmuch_database_open (const char *path, if (err) { fprintf (stderr, "Error opening database at %s: %s\n", notmuch_path, strerror (errno)); + status = NOTMUCH_STATUS_FILE_ERROR; goto DONE; } if (! (xapian_path = talloc_asprintf (local, "%s/%s", notmuch_path, "xapian"))) { fprintf (stderr, "Out of memory\n"); + status = NOTMUCH_STATUS_OUT_OF_MEMORY; goto DONE; } @@ -644,6 +656,7 @@ notmuch_database_open (const char *path, notmuch->mode = NOTMUCH_DATABASE_MODE_READ_ONLY; notmuch_database_destroy (notmuch); notmuch = NULL; + status = NOTMUCH_STATUS_FILE_ERROR; goto DONE; } @@ -704,12 +717,17 @@ notmuch_database_open (const char *path, error.get_msg().c_str()); notmuch_database_destroy (notmuch); notmuch = NULL; + status = NOTMUCH_STATUS_XAPIAN_EXCEPTION; } DONE: talloc_free (local); - return notmuch; + if (database) + *database = notmuch; + else + talloc_free (notmuch); + return status; } void diff --git a/lib/notmuch.h b/lib/notmuch.h index 7d9e092..44b0c46 100644 --- a/lib/notmuch.h +++ b/lib/notmuch.h @@ -151,9 +151,6 @@ typedef enum { NOTMUCH_DATABASE_MODE_READ_WRITE } notmuch_database_mode_t; -/* XXX: I think I'd like this to take an extra argument of - * notmuch_status_t* for returning a status value on failure. */ - /* Open an existing notmuch database located at 'path'. * * The database should have been created at some time in the past, @@ -168,12 +165,27 @@ typedef enum { * The caller should call notmuch_database_destroy when finished with * this database. * - * In case of any failure, this function returns NULL, (after printing - * an error message on stderr). + * In case of any failure, this function returns an error status and + * sets *database to NULL (after printing an error message on stderr). + * + * Return value: + * + * NOTMUCH_STATUS_SUCCESS: Successfully opened the database. + * + * NOTMUCH_STATUS_NULL_POINTER: The given 'path' argument is NULL. + * + * NOTMUCH_STATUS_OUT_OF_MEMORY: Out of memory. + * + * NOTMUCH_STATUS_FILE_ERROR: An error occurred trying to open the + * database file (such as permission denied, or file not found, + * etc.), or the database version is unknown. + * + * NOTMUCH_STATUS_XAPIAN_EXCEPTION: A Xapian exception occurred. */ -notmuch_database_t * +notmuch_status_t notmuch_database_open (const char *path, - notmuch_database_mode_t mode); + notmuch_database_mode_t mode, + notmuch_database_t **database); /* Close the given notmuch database. * diff --git a/notmuch-count.c b/notmuch-count.c index 9c2ad7b..2f98128 100644 --- a/notmuch-count.c +++ b/notmuch-count.c @@ -66,9 +66,8 @@ notmuch_count_command (void *ctx, int argc, char *argv[]) if (config == NULL) return 1; - notmuch = notmuch_database_open (notmuch_config_get_database_path (config), - NOTMUCH_DATABASE_MODE_READ_ONLY); - if (notmuch == NULL) + if (notmuch_database_open (notmuch_config_get_database_path (config), + NOTMUCH_DATABASE_MODE_READ_ONLY, ¬much)) return 1; query_str = query_string_from_args (ctx, argc-opt_index, argv+opt_index); diff --git a/notmuch-dump.c b/notmuch-dump.c index 71ab0ea..3743214 100644 --- a/notmuch-dump.c +++ b/notmuch-dump.c @@ -36,9 +36,8 @@ notmuch_dump_command (unused (void *ctx), int argc, char *argv[]) if (config == NULL) return 1; - notmuch = notmuch_database_open (notmuch_config_get_database_path (config), - NOTMUCH_DATABASE_MODE_READ_ONLY); - if (notmuch == NULL) + if (notmuch_database_open (notmuch_config_get_database_path (config), + NOTMUCH_DATABASE_MODE_READ_ONLY, ¬much)) return 1; char *output_file_name = NULL; diff --git a/notmuch-new.c b/notmuch-new.c index 3ff6304..7788743 100644 --- a/notmuch-new.c +++ b/notmuch-new.c @@ -903,9 +903,8 @@ notmuch_new_command (void *ctx, int argc, char *argv[]) notmuch = notmuch_database_create (db_path); add_files_state.total_files = count; } else { - notmuch = notmuch_database_open (db_path, - NOTMUCH_DATABASE_MODE_READ_WRITE); - if (notmuch == NULL) + if (notmuch_database_open (db_path, NOTMUCH_DATABASE_MODE_READ_WRITE, + ¬much)) return 1; if (notmuch_database_needs_upgrade (notmuch)) { diff --git a/notmuch-reply.c b/notmuch-reply.c index da99a13..7184a5d 100644 --- a/notmuch-reply.c +++ b/notmuch-reply.c @@ -740,9 +740,8 @@ notmuch_reply_command (void *ctx, int argc, char *argv[]) return 1; } - notmuch = notmuch_database_open (notmuch_config_get_database_path (config), - NOTMUCH_DATABASE_MODE_READ_ONLY); - if (notmuch == NULL) + if (notmuch_database_open (notmuch_config_get_database_path (config), + NOTMUCH_DATABASE_MODE_READ_ONLY, ¬much)) return 1; query = notmuch_query_create (notmuch, query_string); diff --git a/notmuch-restore.c b/notmuch-restore.c index 02b563c..4f4096e 100644 --- a/notmuch-restore.c +++ b/notmuch-restore.c @@ -115,9 +115,8 @@ notmuch_restore_command (unused (void *ctx), int argc, char *argv[]) if (config == NULL) return 1; - notmuch = notmuch_database_open (notmuch_config_get_database_path (config), - NOTMUCH_DATABASE_MODE_READ_WRITE); - if (notmuch == NULL) + if (notmuch_database_open (notmuch_config_get_database_path (config), + NOTMUCH_DATABASE_MODE_READ_WRITE, ¬much)) return 1; synchronize_flags = notmuch_config_get_maildir_synchronize_flags (config); diff --git a/notmuch-search.c b/notmuch-search.c index 7dfd270..3be296d 100644 --- a/notmuch-search.c +++ b/notmuch-search.c @@ -486,9 +486,8 @@ notmuch_search_command (void *ctx, int argc, char *argv[]) if (config == NULL) return 1; - notmuch = notmuch_database_open (notmuch_config_get_database_path (config), - NOTMUCH_DATABASE_MODE_READ_ONLY); - if (notmuch == NULL) + if (notmuch_database_open (notmuch_config_get_database_path (config), + NOTMUCH_DATABASE_MODE_READ_ONLY, ¬much)) return 1; query_str = query_string_from_args (notmuch, argc-opt_index, argv+opt_index); diff --git a/notmuch-show.c b/notmuch-show.c index 3b6667c..95427d4 100644 --- a/notmuch-show.c +++ b/notmuch-show.c @@ -1081,9 +1081,8 @@ notmuch_show_command (void *ctx, unused (int argc), unused (char *argv[])) return 1; } - notmuch = notmuch_database_open (notmuch_config_get_database_path (config), - NOTMUCH_DATABASE_MODE_READ_ONLY); - if (notmuch == NULL) + if (notmuch_database_open (notmuch_config_get_database_path (config), + NOTMUCH_DATABASE_MODE_READ_ONLY, ¬much)) return 1; query = notmuch_query_create (notmuch, query_string); diff --git a/notmuch-tag.c b/notmuch-tag.c index bd56fd1..7d18639 100644 --- a/notmuch-tag.c +++ b/notmuch-tag.c @@ -229,9 +229,8 @@ notmuch_tag_command (void *ctx, int argc, char *argv[]) if (config == NULL) return 1; - notmuch = notmuch_database_open (notmuch_config_get_database_path (config), - NOTMUCH_DATABASE_MODE_READ_WRITE); - if (notmuch == NULL) + if (notmuch_database_open (notmuch_config_get_database_path (config), + NOTMUCH_DATABASE_MODE_READ_WRITE, ¬much)) return 1; synchronize_flags = notmuch_config_get_maildir_synchronize_flags (config); diff --git a/test/symbol-test.cc b/test/symbol-test.cc index 1548ca4..3e96c03 100644 --- a/test/symbol-test.cc +++ b/test/symbol-test.cc @@ -4,7 +4,8 @@ int main() { - (void) notmuch_database_open("fakedb", NOTMUCH_DATABASE_MODE_READ_ONLY); + notmuch_database_t *notmuch; + notmuch_database_open("fakedb", NOTMUCH_DATABASE_MODE_READ_ONLY, ¬much); try { (void) new Xapian::WritableDatabase("./nonexistant", Xapian::DB_OPEN); -- cgit v1.2.3 From 7fb8ab9f0b470dc236c92686ed33f8e0fa1d5727 Mon Sep 17 00:00:00 2001 From: Adam Wolfe Gordon Date: Sat, 5 May 2012 13:24:28 -0600 Subject: test: Replying to an HTML-only message in emacs With the latest reply infrastructure, we should be able to nicely quote HTML-only emails. But currently emacs quotes the raw HTML instead of parsing it first. This commit adds a test for this case. This test currently marked as broken. --- test/emacs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'test') diff --git a/test/emacs b/test/emacs index 38decd0..5f238d9 100755 --- a/test/emacs +++ b/test/emacs @@ -444,6 +444,33 @@ Alex Botero-Lowry writes: EOF test_expect_equal_file OUTPUT EXPECTED +test_begin_subtest "Reply within emacs to an html-only message" +test_subtest_known_broken +add_message '[content-type]="text/html"' \ + '[body]="Hi,
This is an HTML test message.

OK?"' +test_emacs "(let ((message-hidden-headers '())) + (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 <EXPECTED +From: Notmuch Test Suite +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 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" \ -- cgit v1.2.3 From f6c170fabca8f39e74705e3813504137811bf162 Mon Sep 17 00:00:00 2001 From: Adam Wolfe Gordon Date: Sat, 5 May 2012 13:30:37 -0600 Subject: emacs: Correctly quote non-text/plain parts in reply Quote non-text parts nicely by displaying them with mm-display-part before calling message-cite-original to quote them. HTML-only emails can now be quoted correctly. We re-use some code from notmuch-show (notmuch-show-mm-display-part-inline), which has been moved to notmuch-lib.el. Mark the test for this feature as not broken. --- emacs/notmuch-lib.el | 19 +++++++++++++++++++ emacs/notmuch-mua.el | 15 ++++++++++----- emacs/notmuch-show.el | 19 +------------------ test/emacs | 1 - 4 files changed, 30 insertions(+), 24 deletions(-) (limited to 'test') diff --git a/emacs/notmuch-lib.el b/emacs/notmuch-lib.el index 6907a5f..7fa441a 100644 --- a/emacs/notmuch-lib.el +++ b/emacs/notmuch-lib.el @@ -21,6 +21,8 @@ ;; This is an part of an emacs-based interface to the notmuch mail system. +(require 'mm-view) +(require 'mm-decode) (eval-when-compile (require 'cl)) (defvar notmuch-command "notmuch" @@ -237,6 +239,23 @@ the given type." (or (plist-get part :content) (notmuch-get-bodypart-internal (notmuch-id-to-query (plist-get msg :id)) nth process-crypto))) +(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 +current buffer, if possible." + (let ((display-buffer (current-buffer))) + (with-temp-buffer + (let* ((charset (plist-get part :content-charset)) + (handle (mm-make-handle (current-buffer) `(,content-type (charset . ,charset))))) + ;; If the user wants the part inlined, insert the content and + ;; test whether we are able to inline it (which includes both + ;; capability and suitability tests). + (when (mm-inlined-p handle) + (insert (notmuch-get-bodypart-content msg part nth process-crypto)) + (when (mm-inlinable-p handle) + (set-buffer display-buffer) + (mm-display-part handle) + t)))))) + ;; Converts a plist of headers to an alist of headers. The input plist should ;; have symbols of the form :Header as keys, and the resulting alist will have ;; symbols of the form 'Header as keys. diff --git a/emacs/notmuch-mua.el b/emacs/notmuch-mua.el index 87bd88d..fc7ae07 100644 --- a/emacs/notmuch-mua.el +++ b/emacs/notmuch-mua.el @@ -21,6 +21,7 @@ (require 'json) (require 'message) +(require 'mm-view) (require 'format-spec) (require 'notmuch-lib) @@ -90,6 +91,14 @@ list." else if (notmuch-match-content-type (plist-get part :content-type) "text/*") collect part)) +(defun notmuch-mua-insert-quotable-part (message part) + (save-restriction + (narrow-to-region (point) (point)) + (notmuch-mm-display-part-inline message part (plist-get part :id) + (plist-get part :content-type) + notmuch-show-process-crypto) + (goto-char (point-max)))) + ;; There is a bug in emacs 23's message.el that results in a newline ;; not being inserted after the References header, so the next header ;; is concatenated to the end of it. This function fixes the problem, @@ -169,11 +178,7 @@ list." ;; Get the parts of the original message that should be quoted; this includes ;; all the text parts, except the non-preferred ones in a multipart/alternative. (let ((quotable-parts (notmuch-mua-get-quotable-parts (plist-get original :body)))) - (mapc (lambda (part) - (insert (notmuch-get-bodypart-content original part - (plist-get part :id) - notmuch-show-process-crypto))) - quotable-parts)) + (mapc (apply-partially 'notmuch-mua-insert-quotable-part original) quotable-parts)) (set-mark (point)) (goto-char start) diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index 37f0ebb..d318430 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -524,23 +524,6 @@ message at DEPTH in the current thread." (let ((handle (mm-make-handle (current-buffer) (list content-type)))) (mm-interactively-view-part handle)))) -(defun notmuch-show-mm-display-part-inline (msg part nth content-type) - "Use the mm-decode/mm-view functions to display a part in the -current buffer, if possible." - (let ((display-buffer (current-buffer))) - (with-temp-buffer - (let* ((charset (plist-get part :content-charset)) - (handle (mm-make-handle (current-buffer) `(,content-type (charset . ,charset))))) - ;; If the user wants the part inlined, insert the content and - ;; test whether we are able to inline it (which includes both - ;; capability and suitability tests). - (when (mm-inlined-p handle) - (insert (notmuch-get-bodypart-content msg part nth notmuch-show-process-crypto)) - (when (mm-inlinable-p handle) - (set-buffer display-buffer) - (mm-display-part handle) - t)))))) - (defun notmuch-show-multipart/*-to-list (part) (mapcar (lambda (inner-part) (plist-get inner-part :content-type)) (plist-get part :content))) @@ -785,7 +768,7 @@ current buffer, if possible." (defun notmuch-show-insert-part-*/* (msg part content-type nth depth declared-type) ;; This handler _must_ succeed - it is the handler of last resort. (notmuch-show-insert-part-header nth content-type declared-type (plist-get part :filename)) - (notmuch-show-mm-display-part-inline msg part nth content-type) + (notmuch-mm-display-part-inline msg part nth content-type notmuch-show-process-crypto) t) ;; Functions for determining how to handle MIME parts. diff --git a/test/emacs b/test/emacs index 5f238d9..a615b39 100755 --- a/test/emacs +++ b/test/emacs @@ -445,7 +445,6 @@ EOF test_expect_equal_file OUTPUT EXPECTED test_begin_subtest "Reply within emacs to an html-only message" -test_subtest_known_broken add_message '[content-type]="text/html"' \ '[body]="Hi,
This is an HTML test message.

OK?"' test_emacs "(let ((message-hidden-headers '())) -- cgit v1.2.3 From 97efed0f0854c2231625057738c1c2db7b37c139 Mon Sep 17 00:00:00 2001 From: Adam Wolfe Gordon Date: Sun, 6 May 2012 08:56:15 -0600 Subject: test: Force reply to use html2text for consistency The output of the HTML reply test in the emacs suite can vary depending on which HTML renderers are installed on the machine running the tests. The renderer that is always available is emacs's builtin html2text function. In order to get consistency, force the test to use html2text even if other renderers are available. --- test/emacs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'test') diff --git a/test/emacs b/test/emacs index a615b39..e9f954c 100755 --- a/test/emacs +++ b/test/emacs @@ -447,7 +447,7 @@ 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,
This is an HTML test message.

OK?"' -test_emacs "(let ((message-hidden-headers '())) +test_emacs "(let ((message-hidden-headers '()) (mm-text-html-renderer 'html2text)) (notmuch-show \"id:${gen_msg_id}\") (notmuch-show-reply) (test-output))" @@ -463,10 +463,7 @@ User-Agent: Notmuch/XXX Emacs/XXX --text follows this line-- Notmuch Test Suite writes: -> Hi, -> This is an HTML test message. -> -> OK? +> Hi,This is an HTML test message.OK? EOF test_expect_equal_file OUTPUT EXPECTED -- cgit v1.2.3 From 512df7ec47a378f9807dd2c19db084fe6e4010ad Mon Sep 17 00:00:00 2001 From: Dmitry Kurochkin Date: Sat, 5 May 2012 18:39:46 +0400 Subject: test: add Emacs notmuch-hello tests for custom tags and queries section. The tests use default values from customization widgets to make sure that these customization widgets work (at least on basic level). The custom queries section test is currently broken. --- test/emacs-hello | 15 +++++++++++++++ .../notmuch-hello-empty-custom-queries-section | 3 +++ .../notmuch-hello-empty-custom-tags-section | 5 +++++ 3 files changed, 23 insertions(+) create mode 100644 test/emacs.expected-output/notmuch-hello-empty-custom-queries-section create mode 100644 test/emacs.expected-output/notmuch-hello-empty-custom-tags-section (limited to 'test') diff --git a/test/emacs-hello b/test/emacs-hello index be66ba4..936d00e 100755 --- a/test/emacs-hello +++ b/test/emacs-hello @@ -44,6 +44,21 @@ test_emacs "(let ((notmuch-hello-sections (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_subtest_known_broken +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 '*' diff --git a/test/emacs.expected-output/notmuch-hello-empty-custom-queries-section b/test/emacs.expected-output/notmuch-hello-empty-custom-queries-section new file mode 100644 index 0000000..cd0fdf0 --- /dev/null +++ b/test/emacs.expected-output/notmuch-hello-empty-custom-queries-section @@ -0,0 +1,3 @@ +: [hide] + + diff --git a/test/emacs.expected-output/notmuch-hello-empty-custom-tags-section b/test/emacs.expected-output/notmuch-hello-empty-custom-tags-section new file mode 100644 index 0000000..b56fd67 --- /dev/null +++ b/test/emacs.expected-output/notmuch-hello-empty-custom-tags-section @@ -0,0 +1,5 @@ +: [hide] + + 4 attachment 7 signed + 52 inbox 52 unread + -- cgit v1.2.3 From 4997ec95719a50a1882ec9b84dcb31e7984a3565 Mon Sep 17 00:00:00 2001 From: Dmitry Kurochkin Date: Sat, 5 May 2012 18:39:47 +0400 Subject: emacs: fix custom queries section customization widget in notmuch-hello The customization widget referred to a non-existing function `notmuch-hello-insert-query-list'. The patch changes it to the correct one - `notmuch-hello-insert-searches'. The relevant test is fixed now. --- emacs/notmuch-hello.el | 2 +- test/emacs-hello | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'test') diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el index f10d98d..684bedc 100644 --- a/emacs/notmuch-hello.el +++ b/emacs/notmuch-hello.el @@ -187,7 +187,7 @@ This should only be set by `notmuch-hello-insert-search'.") :tag "Customized queries section (see docstring for details)" :type `(list :tag "" - (const :tag "" notmuch-hello-insert-query-list) + (const :tag "" notmuch-hello-insert-searches) (string :tag "Title for this section") (repeat :tag "Queries" (cons (string :tag "Name") (string :tag "Query"))) diff --git a/test/emacs-hello b/test/emacs-hello index 936d00e..a998dc4 100755 --- a/test/emacs-hello +++ b/test/emacs-hello @@ -52,7 +52,6 @@ test_emacs "(let* ((widget (widget-create 'notmuch-hello-tags-section)) test_expect_equal_file OUTPUT $EXPECTED/notmuch-hello-empty-custom-tags-section test_begin_subtest "Empty custom queries section" -test_subtest_known_broken test_emacs "(let* ((widget (widget-create 'notmuch-hello-query-section)) (notmuch-hello-sections (list (widget-value widget)))) (notmuch-hello) -- cgit v1.2.3 From 54508eb78d1c5c1c67c8b220cf2bd826af1203a9 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Fri, 18 May 2012 00:13:41 -0400 Subject: python: Remove find_message_by_filename workaround Now that notmuch_database_find_message_by_filename works on read-only databases, remove the workaround that disabled it on read-write databases. This also adds a regression test for find_message_by_filename. --- bindings/python/notmuch/database.py | 9 --------- test/python | 8 ++++++++ 2 files changed, 8 insertions(+), 9 deletions(-) (limited to 'test') diff --git a/bindings/python/notmuch/database.py b/bindings/python/notmuch/database.py index ff89818..e5c74cf 100644 --- a/bindings/python/notmuch/database.py +++ b/bindings/python/notmuch/database.py @@ -526,19 +526,10 @@ class Database(object): retry. :raises: :exc:`NotInitializedError` if the database was not intitialized. - :raises: :exc:`ReadOnlyDatabaseError` if the database has not been - opened in read-write mode *Added in notmuch 0.9*""" self._assert_db_is_initialized() - # work around libnotmuch calling exit(3), see - # id:20120221002921.8534.57091@thinkbox.jade-hamburg.de - # TODO: remove once this issue is resolved - if self.mode != Database.MODE.READ_WRITE: - raise ReadOnlyDatabaseError('The database has to be opened in ' - 'read-write mode for get_directory') - msg_p = NotmuchMessageP() status = Database._find_message_by_filename(self._db, _str(filename), byref(msg_p)) diff --git a/test/python b/test/python index 6018c2d..3f03a2e 100755 --- a/test/python +++ b/test/python @@ -28,4 +28,12 @@ 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 < Date: Thu, 24 May 2012 18:01:10 -0400 Subject: test: Test notmuch new with a broken symlink --- test/new | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'test') diff --git a/test/new b/test/new index 99f9913..a7bc146 100755 --- a/test/new +++ b/test/new @@ -136,6 +136,16 @@ 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 directory ${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 -- cgit v1.2.3 From d99270c450d8f9ef3ecfbcbeeb99b581f36c9175 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Thu, 24 May 2012 18:01:11 -0400 Subject: new: Centralize file type stat-ing logic This moves our logic to get a file's type into one function. This has several benefits: we can support OSes and file systems that do not provide dirent.d_type or always return DT_UNKNOWN, complex symlink-handling logic has been replaced by a simple stat fall-through in one place, and the error message for un-stat-able file is more accurate (previously, the error always mentioned directories, even though a broken symlink is not a directory). --- notmuch-new.c | 103 +++++++++++++++++++++++++++++++++++----------------------- test/new | 2 +- 2 files changed, 64 insertions(+), 41 deletions(-) (limited to 'test') diff --git a/notmuch-new.c b/notmuch-new.c index 72dd558..c64f1a7 100644 --- a/notmuch-new.c +++ b/notmuch-new.c @@ -154,6 +154,48 @@ dirent_sort_strcmp_name (const struct dirent **a, const struct dirent **b) return strcmp ((*a)->d_name, (*b)->d_name); } +/* Return the type of a directory entry relative to path as a stat(2) + * mode. Like stat, this follows symlinks. Returns -1 and sets errno + * if the file's type cannot be determined (which includes dangling + * symlinks). + */ +static int +dirent_type (const char *path, const struct dirent *entry) +{ + struct stat statbuf; + char *abspath; + int err, saved_errno; + +#ifdef _DIRENT_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[] = { + [DT_BLK] = S_IFBLK, + [DT_CHR] = S_IFCHR, + [DT_DIR] = S_IFDIR, + [DT_FIFO] = S_IFIFO, + [DT_REG] = S_IFREG, + [DT_SOCK] = S_IFSOCK + }; + if (entry->d_type < ARRAY_SIZE(modes) && modes[entry->d_type]) + return modes[entry->d_type]; +#endif + + abspath = talloc_asprintf (NULL, "%s/%s", path, entry->d_name); + if (!abspath) { + errno = ENOMEM; + return -1; + } + err = stat(abspath, &statbuf); + saved_errno = errno; + talloc_free (abspath); + if (err < 0) { + errno = saved_errno; + return -1; + } + return statbuf.st_mode & S_IFMT; +} + /* Test if the directory looks like a Maildir directory. * * Search through the array of directory entries to see if we can find all @@ -162,12 +204,12 @@ dirent_sort_strcmp_name (const struct dirent **a, const struct dirent **b) * Return 1 if the directory looks like a Maildir and 0 otherwise. */ static int -_entries_resemble_maildir (struct dirent **entries, int count) +_entries_resemble_maildir (const char *path, struct dirent **entries, int count) { int i, found = 0; for (i = 0; i < count; i++) { - if (entries[i]->d_type != DT_DIR && entries[i]->d_type != DT_UNKNOWN) + if (dirent_type (path, entries[i]) != S_IFDIR) continue; if (strcmp(entries[i]->d_name, "new") == 0 || @@ -250,7 +292,7 @@ add_files_recursive (notmuch_database_t *notmuch, notmuch_status_t status, ret = NOTMUCH_STATUS_SUCCESS; notmuch_message_t *message = NULL; struct dirent **fs_entries = NULL; - int i, num_fs_entries = 0; + int i, num_fs_entries = 0, entry_type; notmuch_directory_t *directory; notmuch_filenames_t *db_files = NULL; notmuch_filenames_t *db_subdirs = NULL; @@ -300,7 +342,7 @@ add_files_recursive (notmuch_database_t *notmuch, } /* Pass 1: Recurse into all sub-directories. */ - is_maildir = _entries_resemble_maildir (fs_entries, num_fs_entries); + is_maildir = _entries_resemble_maildir (path, fs_entries, num_fs_entries); for (i = 0; i < num_fs_entries; i++) { if (interrupted) @@ -308,17 +350,16 @@ add_files_recursive (notmuch_database_t *notmuch, entry = fs_entries[i]; - /* We only want to descend into directories. - * But symlinks can be to directories too, of course. - * - * And if the filesystem doesn't tell us the file type in the - * scandir results, then it might be a directory (and if not, - * then we'll stat and return immediately in the next level of - * recursion). */ - if (entry->d_type != DT_DIR && - entry->d_type != DT_LNK && - entry->d_type != DT_UNKNOWN) - { + /* We only want to descend into directories (and symlinks to + * directories). */ + entry_type = dirent_type (path, entry); + if (entry_type == -1) { + /* Be pessimistic, e.g. so we don't lose lots of mail just + * because a user broke a symlink. */ + fprintf (stderr, "Error reading file %s/%s: %s\n", + path, entry->d_name, strerror (errno)); + return NOTMUCH_STATUS_FILE_ERROR; + } else if (entry_type != S_IFDIR) { continue; } @@ -407,31 +448,13 @@ add_files_recursive (notmuch_database_t *notmuch, notmuch_filenames_move_to_next (db_subdirs); } - /* If we're looking at a symlink, we only want to add it if it - * links to a regular file, (and not to a directory, say). - * - * Similarly, if the file is of unknown type (due to filesystem - * limitations), then we also need to look closer. - * - * In either case, a stat does the trick. - */ - if (entry->d_type == DT_LNK || entry->d_type == DT_UNKNOWN) { - int err; - - next = talloc_asprintf (notmuch, "%s/%s", path, entry->d_name); - err = stat (next, &st); - talloc_free (next); - next = NULL; - - /* Don't emit an error for a link pointing nowhere, since - * the directory-traversal pass will have already done - * that. */ - if (err) - continue; - - if (! S_ISREG (st.st_mode)) - continue; - } else if (entry->d_type != DT_REG) { + /* Only add regular files (and symlinks to regular files). */ + entry_type = dirent_type (path, entry); + if (entry_type == -1) { + fprintf (stderr, "Error reading file %s/%s: %s\n", + path, entry->d_name, strerror (errno)); + return NOTMUCH_STATUS_FILE_ERROR; + } else if (entry_type != S_IFREG) { continue; } diff --git a/test/new b/test/new index a7bc146..cab7c01 100755 --- a/test/new +++ b/test/new @@ -140,7 +140,7 @@ 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 directory ${MAIL_DIR}/broken: No such file or directory +"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" -- cgit v1.2.3 From 2f1a11268f2d230d0b3786a158b238e45090b768 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 24 May 2012 08:15:50 +0300 Subject: test: add tests for notmuch reply From guessing Add tests for picking up user's From address from fallback headers Envelope-To, X-Original-To, and Delivered-To. Signed-off-by: Jani Nikula --- test/reply | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) (limited to 'test') diff --git a/test/reply b/test/reply index 00f4bea..ee5d361 100755 --- a/test/reply +++ b/test/reply @@ -138,4 +138,59 @@ References: <${gen_msg_id}> On Tue, 05 Jan 2010 15:43:56 -0000, Notmuch Test Suite wrote: > 200-byte header" + +test_begin_subtest "From guessing: Envelope-To" +add_message '[from]="Sender "' \ + '[to]="Recipient "' \ + '[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 +Subject: Re: From guessing +To: Sender , Recipient +In-Reply-To: <${gen_msg_id}> +References: <${gen_msg_id}> + +On Tue, 05 Jan 2010 15:43:56 -0000, Sender wrote: +> From guessing" + +test_begin_subtest "From guessing: X-Original-To" +add_message '[from]="Sender "' \ + '[to]="Recipient "' \ + '[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 +Subject: Re: From guessing +To: Sender , Recipient +In-Reply-To: <${gen_msg_id}> +References: <${gen_msg_id}> + +On Tue, 05 Jan 2010 15:43:56 -0000, Sender wrote: +> From guessing" + +test_begin_subtest "From guessing: Delivered-To" +add_message '[from]="Sender "' \ + '[to]="Recipient "' \ + '[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 +Subject: Re: From guessing +To: Sender , Recipient +In-Reply-To: <${gen_msg_id}> +References: <${gen_msg_id}> + +On Tue, 05 Jan 2010 15:43:56 -0000, Sender wrote: +> From guessing" + test_done -- cgit v1.2.3 From 0bef41bf10676c085e4365330ecf6f67d40ae3db Mon Sep 17 00:00:00 2001 From: Dmitry Kurochkin Date: Fri, 25 May 2012 17:02:55 +0400 Subject: test: remove "Testing" from test description in emacs-hello and emacs-show "Testing" is printed by test/test-lib.sh, so having "Testing" in test description results in duplicate "Testing" in console output. --- test/emacs-hello | 2 +- test/emacs-show | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'test') diff --git a/test/emacs-hello b/test/emacs-hello index a998dc4..48d1420 100755 --- a/test/emacs-hello +++ b/test/emacs-hello @@ -1,6 +1,6 @@ #!/usr/bin/env bash -test_description="Testing emacs notmuch-hello view" +test_description="emacs notmuch-hello view" . test-lib.sh EXPECTED=$TEST_DIRECTORY/emacs.expected-output diff --git a/test/emacs-show b/test/emacs-show index 5700d2e..2498564 100755 --- a/test/emacs-show +++ b/test/emacs-show @@ -1,6 +1,6 @@ #!/usr/bin/env bash -test_description="Testing emacs notmuch-show view" +test_description="emacs notmuch-show view" . test-lib.sh test_begin_subtest "Hiding Original Message region at beginning of a message" -- cgit v1.2.3 From 627f7b27f9756287795343cbb8a3137f74efccf9 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 5 Jun 2012 18:42:50 +0300 Subject: test: add test for emacs notmuch-show-strip-re function The function is used for stripping "re:" from subjects to generate "bare subjects". Include broken test for having "re:" in the middle of the subject. --- test/emacs-show | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'test') diff --git a/test/emacs-show b/test/emacs-show index 2498564..1ddb28e 100755 --- a/test/emacs-show +++ b/test/emacs-show @@ -24,4 +24,17 @@ test_emacs "(notmuch-show \"id:$message_id\") (test-visible-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" +test_subtest_known_broken +output=$(test_emacs '(notmuch-show-strip-re "the cure: fix the regexp")') +test_expect_equal "$output" '"the cure: fix the regexp"' + test_done -- cgit v1.2.3 From 0ff57e75cf5847d2cbef97a49badb4cccc618300 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 5 Jun 2012 18:42:51 +0300 Subject: emacs: only strip "re:" in the beginning of subject Fix notmuch-show-strip-re by matching "re:" only in the beginning of the input string. --- emacs/notmuch-show.el | 2 +- test/emacs-show | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'test') diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index d318430..36cad93 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -819,7 +819,7 @@ message at DEPTH in the current thread." (make-symbol (concat "notmuch-show-" type))) (defun notmuch-show-strip-re (string) - (replace-regexp-in-string "\\([Rr]e: *\\)+" "" string)) + (replace-regexp-in-string "^\\([Rr]e: *\\)+" "" string)) (defvar notmuch-show-previous-subject "") (make-variable-buffer-local 'notmuch-show-previous-subject) diff --git a/test/emacs-show b/test/emacs-show index 1ddb28e..e9a714f 100755 --- a/test/emacs-show +++ b/test/emacs-show @@ -33,7 +33,6 @@ output=$(test_emacs '(notmuch-show-strip-re "re:Re: re: Re: re:subject")') test_expect_equal "$output" '"subject"' test_begin_subtest "Bare subject #3" -test_subtest_known_broken output=$(test_emacs '(notmuch-show-strip-re "the cure: fix the regexp")') test_expect_equal "$output" '"the cure: fix the regexp"' -- cgit v1.2.3 From b0d0dab22abd80d826edee7260d1c9cbfdcffd56 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Sat, 9 Jun 2012 15:14:14 -0400 Subject: test: Add broken test for tag synchronization on files delivered to new/ Currently, notmuch new only synchronizes maildir flags to tags for files that have an "info" part. However, in maildir, new mail doesn't gain the info part until it moves from new/ to cur/. Hence, even though mail in new/ doesn't have an info part, it is still a maildir message and thus has maildir flags (though none of them set). The most visible effect of not synchronizing maildir flags for messages in new/ is that newly delivered messages don't get the unread tag (unless it is assigned by some other mechanism, like new.tags). This patch does *not* modify the test for messages in cur/ that do not have an "info" part. Unlike a message in new/, a message in cur/ without an info part is no longer a maildir message, and thus shouldn't be subject to maildir flag synchronization. --- test/maildir-sync | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'test') diff --git a/test/maildir-sync b/test/maildir-sync index d72ec07..6360fd2 100755 --- a/test/maildir-sync +++ b/test/maildir-sync @@ -166,4 +166,14 @@ add_message [subject]='"Non-compliant maildir info"' [dir]=cur [filename]='non-c 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" +test_subtest_known_broken +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 -- cgit v1.2.3 From b88030bda6da084ef74e41f588589fd98e773ad7 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Sat, 9 Jun 2012 15:14:17 -0400 Subject: lib: Treat messages in new/ as maildir messages with no flags set Previously, notmuch new only synchronized maildir flags to tags for files with a maildir "info" part. Since messages in new/ don't have an info part, notmuch would ignore them for flag-to-tag synchronization. This patch makes notmuch consider messages in new/ to be legitimate maildir messages that simply have no maildir flags set. The most visible effect of this is that such messages now automatically get the unread tag. --- lib/message.cc | 20 +++++++++++++------- test/maildir-sync | 1 - 2 files changed, 13 insertions(+), 8 deletions(-) (limited to 'test') diff --git a/lib/message.cc b/lib/message.cc index bbac2ff..978de06 100644 --- a/lib/message.cc +++ b/lib/message.cc @@ -1090,13 +1090,19 @@ notmuch_message_maildir_flags_to_tags (notmuch_message_t *message) continue; flags = strstr (filename, ":2,"); - if (! flags) - continue; - - seen_maildir_info = 1; - flags += 3; - - combined_flags = talloc_strdup_append (combined_flags, flags); + if (flags) { + seen_maildir_info = 1; + flags += 3; + combined_flags = talloc_strdup_append (combined_flags, flags); + } else if (STRNCMP_LITERAL (dir, "new/") == 0) { + /* Messages are delivered to new/ with no "info" part, but + * they effectively have default maildir flags. According + * to the spec, we should ignore the info part for + * messages in new/, but some MUAs (mutt) can set maildir + * flags on messages in new/, so we're liberal in what we + * accept. */ + seen_maildir_info = 1; + } } /* If none of the filenames have any maildir info field (not even diff --git a/test/maildir-sync b/test/maildir-sync index 6360fd2..01348d3 100755 --- a/test/maildir-sync +++ b/test/maildir-sync @@ -167,7 +167,6 @@ 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" -test_subtest_known_broken OLDCONFIG=$(notmuch config get new.tags) notmuch config set new.tags test add_message [subject]='"File in new/"' [dir]=new [filename]='file-in-new' -- cgit v1.2.3 From 9d70e952ebdec48733ab6878e669f9a4eb1812a8 Mon Sep 17 00:00:00 2001 From: Peter Wang Date: Sun, 24 Jun 2012 13:27:48 +1000 Subject: test: add basic show, search --format=text tests There didn't seem to be these basic tests for --format=text, as there are for --format=json. These are just the tests from the `json' script, with adjusted expected outputs. --- test/notmuch-test | 1 + test/text | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100755 test/text (limited to 'test') diff --git a/test/notmuch-test b/test/notmuch-test index bfad5d3..ea39dfc 100755 --- a/test/notmuch-test +++ b/test/notmuch-test @@ -31,6 +31,7 @@ TESTS=" excludes tagging json + text multipart thread-naming raw diff --git a/test/text b/test/text new file mode 100755 index 0000000..428c89b --- /dev/null +++ b/test/text @@ -0,0 +1,55 @@ +#!/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" "\ + message{ id:XXXXX depth:0 match:1 excluded:0 filename:XXXXX + header{ +Notmuch Test Suite (2000-01-01) (inbox unread) +Subject: text-show-subject +From: Notmuch Test Suite +To: Notmuch Test Suite +Date: Sat, 01 Jan 2000 12:00:00 +0000 + header} + body{ + part{ ID: 1, Content-type: text/plain +text-show-message + part} + body} + message}" + +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" "\ + message{ id:XXXXX depth:0 match:1 excluded:0 filename:XXXXX + header{ +Notmuch Test Suite (2000-01-01) (inbox unread) +Subject: text-show-utf8-body-sübjéct +From: Notmuch Test Suite +To: Notmuch Test Suite +Date: Sat, 01 Jan 2000 12:00:00 +0000 + header} + body{ + part{ ID: 1, Content-type: text/plain +tëxt-show-méssage + part} + body} + message}" + +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)" + +test_done -- cgit v1.2.3 From f94a50d80af8c2a5513e58db954dd0b1910eb4a8 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Mon, 9 Jul 2012 17:42:39 -0400 Subject: test: New test for incremental search output parsing This advises the search process filter to make it process one character at a time in order to test the pessimal case for incremental search output parsing. The text parser fails this test because it gets tricked into thinking a parenthetical remark in a subject is the tag list. --- test/emacs | 11 +++++++++++ test/test-lib.el | 8 ++++++++ 2 files changed, 19 insertions(+) (limited to 'test') diff --git a/test/emacs b/test/emacs index e9f954c..293b12a 100755 --- a/test/emacs +++ b/test/emacs @@ -35,6 +35,17 @@ test_emacs '(notmuch-search "tag:inbox") (test-output)' test_expect_equal_file OUTPUT $EXPECTED/notmuch-search-tag-inbox +test_begin_subtest "Incremental parsing of search results" +test_subtest_known_broken +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)) diff --git a/test/test-lib.el b/test/test-lib.el index 6271da2..5dd6271 100644 --- a/test/test-lib.el +++ b/test/test-lib.el @@ -89,6 +89,14 @@ nothing." (add-hook-counter 'notmuch-hello-mode-hook) (add-hook-counter 'notmuch-hello-refresh-hook) +(defadvice notmuch-search-process-filter (around pessimal activate disable) + "Feed notmuch-search-process-filter one character at a time." + (let ((string (ad-get-arg 1))) + (loop for char across string + do (progn + (ad-set-arg 1 (char-to-string char)) + ad-do-it)))) + (defmacro notmuch-test-run (&rest body) "Evaluate a BODY of test expressions and output the result." `(with-temp-buffer -- cgit v1.2.3 From 9c5ea07cc66a00132d20db0c8b2094d25ce564ba Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Mon, 9 Jul 2012 17:42:41 -0400 Subject: emacs: Switch from text to JSON format for search results The JSON format eliminates the complex escaping issues that have plagued the text search format. This uses the incremental JSON parser so that, like the text parser, it can output search results incrementally. This slows down the parser by about ~4X, but puts us in a good position to optimize either by improving the JSON parser (evidence suggests this can reduce the overhead to ~40% over the text format) or by switching to S-expressions (evidence suggests this will more than double performance over the text parser). [1] This also fixes the incremental search parsing test. This has one minor side-effect on search result formatting. Previously, the date field was always padded to a fixed width of 12 characters because of how the text parser's regexp was written. The JSON format doesn't do this. We could pad it out in Emacs before formatting it, but, since all of the other fields are variable width, we instead fix notmuch-search-result-format to take the variable-width field and pad it out. For users who have customized this variable, we'll mention in the NEWS how to fix this slight format change. [1] id:"20110720205007.GB21316@mit.edu" --- emacs/notmuch.el | 110 ++++++++++++++++++++++++++++++++----------------------- test/emacs | 1 - 2 files changed, 64 insertions(+), 47 deletions(-) (limited to 'test') diff --git a/emacs/notmuch.el b/emacs/notmuch.el index dfeaf35..fabb7c0 100644 --- a/emacs/notmuch.el +++ b/emacs/notmuch.el @@ -60,7 +60,7 @@ (require 'notmuch-message) (defcustom notmuch-search-result-format - `(("date" . "%s ") + `(("date" . "%12s ") ("count" . "%-7s ") ("authors" . "%-20s ") ("subject" . "%s ") @@ -557,17 +557,14 @@ This function advances the next thread when finished." (notmuch-search-tag '("-inbox")) (notmuch-search-next-thread)) -(defvar notmuch-search-process-filter-data nil - "Data that has not yet been processed.") -(make-variable-buffer-local 'notmuch-search-process-filter-data) - (defun notmuch-search-process-sentinel (proc msg) "Add a message to let user know when \"notmuch search\" exits" (let ((buffer (process-buffer proc)) (status (process-status proc)) (exit-status (process-exit-status proc)) (never-found-target-thread nil)) - (if (memq status '(exit signal)) + (when (memq status '(exit signal)) + (kill-buffer (process-get proc 'parse-buf)) (if (buffer-live-p buffer) (with-current-buffer buffer (save-excursion @@ -577,8 +574,6 @@ This function advances the next thread when finished." (if (eq status 'signal) (insert "Incomplete search results (search process was killed).\n")) (when (eq status 'exit) - (if notmuch-search-process-filter-data - (insert (concat "Error: Unexpected output from notmuch search:\n" notmuch-search-process-filter-data))) (insert "End of search results.") (unless (= exit-status 0) (insert (format " (process returned %d)" exit-status))) @@ -758,45 +753,59 @@ non-authors is found, assume that all of the authors match." (insert (apply #'format string objects)) (insert "\n"))) +(defvar notmuch-search-process-state nil + "Parsing state of the search process filter.") + +(defvar notmuch-search-json-parser nil + "Incremental JSON parser for the search process filter.") + (defun notmuch-search-process-filter (proc string) "Process and filter the output of \"notmuch search\"" - (let ((buffer (process-buffer proc))) - (if (buffer-live-p buffer) - (with-current-buffer buffer - (let ((line 0) - (more t) - (inhibit-read-only t) - (string (concat notmuch-search-process-filter-data string))) - (setq notmuch-search-process-filter-data nil) - (while more - (while (and (< line (length string)) (= (elt string line) ?\n)) - (setq line (1+ line))) - (if (string-match "^thread:\\([0-9A-Fa-f]*\\) \\([^][]*\\) \\[\\([0-9]*\\)/\\([0-9]*\\)\\] \\([^;]*\\); \\(.*\\) (\\([^()]*\\))$" string line) - (let* ((thread-id (match-string 1 string)) - (tags-str (match-string 7 string)) - (result (list :thread thread-id - :date_relative (match-string 2 string) - :matched (string-to-number - (match-string 3 string)) - :total (string-to-number - (match-string 4 string)) - :authors (match-string 5 string) - :subject (match-string 6 string) - :tags (if tags-str - (save-match-data - (split-string tags-str)))))) - (if (/= (match-beginning 0) line) - (notmuch-search-show-error - (substring string line (match-beginning 0)))) - (notmuch-search-show-result result) - (set 'line (match-end 0))) - (set 'more nil) - (while (and (< line (length string)) (= (elt string line) ?\n)) - (setq line (1+ line))) - (if (< line (length string)) - (setq notmuch-search-process-filter-data (substring string line))) - )))) - (delete-process proc)))) + (let ((results-buf (process-buffer proc)) + (parse-buf (process-get proc 'parse-buf)) + (inhibit-read-only t) + done) + (if (not (buffer-live-p results-buf)) + (delete-process proc) + (with-current-buffer parse-buf + ;; Insert new data + (save-excursion + (goto-char (point-max)) + (insert string))) + (with-current-buffer results-buf + (while (not done) + (condition-case nil + (case notmuch-search-process-state + ((begin) + ;; Enter the results list + (if (eq (notmuch-json-begin-compound + notmuch-search-json-parser) 'retry) + (setq done t) + (setq notmuch-search-process-state 'result))) + ((result) + ;; Parse a result + (let ((result (notmuch-json-read notmuch-search-json-parser))) + (case result + ((retry) (setq done t)) + ((end) (setq notmuch-search-process-state 'end)) + (otherwise (notmuch-search-show-result result))))) + ((end) + ;; Any trailing data is unexpected + (notmuch-json-eof notmuch-search-json-parser) + (setq done t))) + (json-error + ;; Do our best to resynchronize and ensure forward + ;; progress + (notmuch-search-show-error + "%s" + (with-current-buffer parse-buf + (let ((bad (buffer-substring (line-beginning-position) + (line-end-position)))) + (forward-line) + bad)))))) + ;; Clear out what we've parsed + (with-current-buffer parse-buf + (delete-region (point-min) (point))))))) (defun notmuch-search-tag-all (&optional tag-changes) "Add/remove tags from all messages in current search buffer. @@ -899,10 +908,19 @@ Other optional parameters are used as follows: (let ((proc (start-process "notmuch-search" buffer notmuch-command "search" + "--format=json" (if oldest-first "--sort=oldest-first" "--sort=newest-first") - query))) + query)) + ;; Use a scratch buffer to accumulate partial output. + ;; This buffer will be killed by the sentinel, which + ;; should be called no matter how the process dies. + (parse-buf (generate-new-buffer " *notmuch search parse*"))) + (set (make-local-variable 'notmuch-search-process-state) 'begin) + (set (make-local-variable 'notmuch-search-json-parser) + (notmuch-json-create-parser parse-buf)) + (process-put proc 'parse-buf parse-buf) (set-process-sentinel proc 'notmuch-search-process-sentinel) (set-process-filter proc 'notmuch-search-process-filter) (set-process-query-on-exit-flag proc nil)))) diff --git a/test/emacs b/test/emacs index 293b12a..afe35ba 100755 --- a/test/emacs +++ b/test/emacs @@ -36,7 +36,6 @@ test_emacs '(notmuch-search "tag:inbox") test_expect_equal_file OUTPUT $EXPECTED/notmuch-search-tag-inbox test_begin_subtest "Incremental parsing of search results" -test_subtest_known_broken test_emacs "(ad-enable-advice 'notmuch-search-process-filter 'around 'pessimal) (ad-activate 'notmuch-search-process-filter) (notmuch-search \"tag:inbox\") -- cgit v1.2.3 From 10ab2b57039d7ef06c82749530ff48675e81d16d Mon Sep 17 00:00:00 2001 From: "craven@gmx.net" Date: Mon, 23 Jul 2012 12:39:46 +0200 Subject: Use the structured formatters in notmuch-search.c. This patch switches from the current ad-hoc printer to the structured formatters in sprinter.h, sprinter-text.c and sprinter-json.c. The JSON tests are changed slightly in order to make them PASS for the new structured output formatter. The text tests pass without adaptation. --- notmuch-search.c | 304 ++++++++++++++++--------------------------------------- test/json | 34 ++++--- 2 files changed, 106 insertions(+), 232 deletions(-) (limited to 'test') diff --git a/notmuch-search.c b/notmuch-search.c index 3be296d..830c4e4 100644 --- a/notmuch-search.c +++ b/notmuch-search.c @@ -19,6 +19,7 @@ */ #include "notmuch-client.h" +#include "sprinter.h" typedef enum { OUTPUT_SUMMARY, @@ -28,92 +29,6 @@ typedef enum { OUTPUT_TAGS } output_t; -typedef struct search_format { - const char *results_start; - const char *item_start; - void (*item_id) (const void *ctx, - const char *item_type, - const char *item_id); - void (*thread_summary) (const void *ctx, - const char *thread_id, - const time_t date, - const int matched, - const int total, - const char *authors, - const char *subject); - const char *tag_start; - const char *tag; - const char *tag_sep; - const char *tag_end; - const char *item_sep; - const char *item_end; - const char *results_end; - const char *results_null; -} search_format_t; - -static void -format_item_id_text (const void *ctx, - const char *item_type, - const char *item_id); - -static void -format_thread_text (const void *ctx, - const char *thread_id, - const time_t date, - const int matched, - const int total, - const char *authors, - const char *subject); -static const search_format_t format_text = { - "", - "", - format_item_id_text, - format_thread_text, - " (", - "%s", " ", - ")", "\n", - "", - "\n", - "", -}; - -static void -format_item_id_json (const void *ctx, - const char *item_type, - const char *item_id); - -static void -format_thread_json (const void *ctx, - const char *thread_id, - const time_t date, - const int matched, - const int total, - const char *authors, - const char *subject); - -/* Any changes to the JSON format should be reflected in the file - * devel/schemata. */ -static const search_format_t format_json = { - "[", - "{", - format_item_id_json, - format_thread_json, - "\"tags\": [", - "\"%s\"", ", ", - "]", ",\n", - "}", - "]\n", - "]\n", -}; - -static void -format_item_id_text (unused (const void *ctx), - const char *item_type, - const char *item_id) -{ - printf ("%s%s", item_type, item_id); -} - static char * sanitize_string (const void *ctx, const char *str) { @@ -131,72 +46,8 @@ sanitize_string (const void *ctx, const char *str) return out; } -static void -format_thread_text (const void *ctx, - const char *thread_id, - const time_t date, - const int matched, - const int total, - const char *authors, - const char *subject) -{ - void *ctx_quote = talloc_new (ctx); - - printf ("thread:%s %12s [%d/%d] %s; %s", - thread_id, - notmuch_time_relative_date (ctx, date), - matched, - total, - sanitize_string (ctx_quote, authors), - sanitize_string (ctx_quote, subject)); - - talloc_free (ctx_quote); -} - -static void -format_item_id_json (const void *ctx, - unused (const char *item_type), - const char *item_id) -{ - void *ctx_quote = talloc_new (ctx); - - printf ("%s", json_quote_str (ctx_quote, item_id)); - - talloc_free (ctx_quote); - -} - -static void -format_thread_json (const void *ctx, - const char *thread_id, - const time_t date, - const int matched, - const int total, - const char *authors, - const char *subject) -{ - void *ctx_quote = talloc_new (ctx); - - printf ("\"thread\": %s,\n" - "\"timestamp\": %ld,\n" - "\"date_relative\": \"%s\",\n" - "\"matched\": %d,\n" - "\"total\": %d,\n" - "\"authors\": %s,\n" - "\"subject\": %s,\n", - json_quote_str (ctx_quote, thread_id), - date, - notmuch_time_relative_date (ctx, date), - matched, - total, - json_quote_str (ctx_quote, authors), - json_quote_str (ctx_quote, subject)); - - talloc_free (ctx_quote); -} - static int -do_search_threads (const search_format_t *format, +do_search_threads (sprinter_t *format, notmuch_query_t *query, notmuch_sort_t sort, output_t output, @@ -207,7 +58,6 @@ do_search_threads (const search_format_t *format, notmuch_threads_t *threads; notmuch_tags_t *tags; time_t date; - int first_thread = 1; int i; if (offset < 0) { @@ -220,14 +70,12 @@ do_search_threads (const search_format_t *format, if (threads == NULL) return 1; - fputs (format->results_start, stdout); + format->begin_list (format); for (i = 0; notmuch_threads_valid (threads) && (limit < 0 || i < offset + limit); notmuch_threads_move_to_next (threads), i++) { - int first_tag = 1; - thread = notmuch_threads_get (threads); if (i < offset) { @@ -235,60 +83,97 @@ do_search_threads (const search_format_t *format, continue; } - if (! first_thread) - fputs (format->item_sep, stdout); - if (output == OUTPUT_THREADS) { - format->item_id (thread, "thread:", - notmuch_thread_get_thread_id (thread)); + format->set_prefix (format, "thread"); + format->string (format, + notmuch_thread_get_thread_id (thread)); + format->separator (format); } else { /* output == OUTPUT_SUMMARY */ - fputs (format->item_start, stdout); + void *ctx_quote = talloc_new (thread); + const char *authors = notmuch_thread_get_authors (thread); + const char *subject = notmuch_thread_get_subject (thread); + const char *thread_id = notmuch_thread_get_thread_id (thread); + int matched = notmuch_thread_get_matched_messages (thread); + int total = notmuch_thread_get_total_messages (thread); + const char *relative_date = NULL; + notmuch_bool_t first_tag = TRUE; + + format->begin_map (format); if (sort == NOTMUCH_SORT_OLDEST_FIRST) date = notmuch_thread_get_oldest_date (thread); else date = notmuch_thread_get_newest_date (thread); - format->thread_summary (thread, - notmuch_thread_get_thread_id (thread), - date, - notmuch_thread_get_matched_messages (thread), - notmuch_thread_get_total_messages (thread), - notmuch_thread_get_authors (thread), - notmuch_thread_get_subject (thread)); + relative_date = notmuch_time_relative_date (ctx_quote, date); + + if (format->is_text_printer) { + /* Special case for the text formatter */ + printf ("thread:%s %12s [%d/%d] %s; %s (", + thread_id, + relative_date, + matched, + total, + sanitize_string (ctx_quote, authors), + sanitize_string (ctx_quote, subject)); + } else { /* Structured Output */ + format->map_key (format, "thread"); + format->string (format, thread_id); + format->map_key (format, "timestamp"); + format->integer (format, date); + format->map_key (format, "date_relative"); + format->string (format, relative_date); + format->map_key (format, "matched"); + format->integer (format, matched); + format->map_key (format, "total"); + format->integer (format, total); + format->map_key (format, "authors"); + format->string (format, authors); + format->map_key (format, "subject"); + format->string (format, subject); + } + + talloc_free (ctx_quote); - fputs (format->tag_start, stdout); + format->map_key (format, "tags"); + format->begin_list (format); for (tags = notmuch_thread_get_tags (thread); notmuch_tags_valid (tags); notmuch_tags_move_to_next (tags)) { - if (! first_tag) - fputs (format->tag_sep, stdout); - printf (format->tag, notmuch_tags_get (tags)); - first_tag = 0; + const char *tag = notmuch_tags_get (tags); + + if (format->is_text_printer) { + /* Special case for the text formatter */ + if (first_tag) + first_tag = FALSE; + else + fputc (' ', stdout); + fputs (tag, stdout); + } else { /* Structured Output */ + format->string (format, tag); + } } - fputs (format->tag_end, stdout); + if (format->is_text_printer) + printf (")"); - fputs (format->item_end, stdout); + format->end (format); + format->end (format); + format->separator (format); } - first_thread = 0; - notmuch_thread_destroy (thread); } - if (first_thread) - fputs (format->results_null, stdout); - else - fputs (format->results_end, stdout); + format->end (format); return 0; } static int -do_search_messages (const search_format_t *format, +do_search_messages (sprinter_t *format, notmuch_query_t *query, output_t output, int offset, @@ -297,7 +182,6 @@ do_search_messages (const search_format_t *format, notmuch_message_t *message; notmuch_messages_t *messages; notmuch_filenames_t *filenames; - int first_message = 1; int i; if (offset < 0) { @@ -310,7 +194,7 @@ do_search_messages (const search_format_t *format, if (messages == NULL) return 1; - fputs (format->results_start, stdout); + format->begin_list (format); for (i = 0; notmuch_messages_valid (messages) && (limit < 0 || i < offset + limit); @@ -328,24 +212,17 @@ do_search_messages (const search_format_t *format, notmuch_filenames_valid (filenames); notmuch_filenames_move_to_next (filenames)) { - if (! first_message) - fputs (format->item_sep, stdout); - - format->item_id (message, "", - notmuch_filenames_get (filenames)); - - first_message = 0; + format->string (format, notmuch_filenames_get (filenames)); + format->separator (format); } notmuch_filenames_destroy( filenames ); } else { /* output == OUTPUT_MESSAGES */ - if (! first_message) - fputs (format->item_sep, stdout); - - format->item_id (message, "id:", - notmuch_message_get_message_id (message)); - first_message = 0; + format->set_prefix (format, "id"); + format->string (format, + notmuch_message_get_message_id (message)); + format->separator (format); } notmuch_message_destroy (message); @@ -353,23 +230,19 @@ do_search_messages (const search_format_t *format, notmuch_messages_destroy (messages); - if (first_message) - fputs (format->results_null, stdout); - else - fputs (format->results_end, stdout); + format->end (format); return 0; } static int do_search_tags (notmuch_database_t *notmuch, - const search_format_t *format, + sprinter_t *format, notmuch_query_t *query) { notmuch_messages_t *messages = NULL; notmuch_tags_t *tags; const char *tag; - int first_tag = 1; /* should the following only special case if no excluded terms * specified? */ @@ -387,7 +260,7 @@ do_search_tags (notmuch_database_t *notmuch, if (tags == NULL) return 1; - fputs (format->results_start, stdout); + format->begin_list (format); for (; notmuch_tags_valid (tags); @@ -395,12 +268,9 @@ do_search_tags (notmuch_database_t *notmuch, { tag = notmuch_tags_get (tags); - if (! first_tag) - fputs (format->item_sep, stdout); - - format->item_id (tags, "", tag); + format->string (format, tag); + format->separator (format); - first_tag = 0; } notmuch_tags_destroy (tags); @@ -408,10 +278,7 @@ do_search_tags (notmuch_database_t *notmuch, if (messages) notmuch_messages_destroy (messages); - if (first_tag) - fputs (format->results_null, stdout); - else - fputs (format->results_end, stdout); + format->end (format); return 0; } @@ -430,7 +297,7 @@ notmuch_search_command (void *ctx, int argc, char *argv[]) notmuch_query_t *query; char *query_str; notmuch_sort_t sort = NOTMUCH_SORT_NEWEST_FIRST; - const search_format_t *format = &format_text; + sprinter_t *format = NULL; int opt_index, ret; output_t output = OUTPUT_SUMMARY; int offset = 0; @@ -475,11 +342,14 @@ notmuch_search_command (void *ctx, int argc, char *argv[]) switch (format_sel) { case NOTMUCH_FORMAT_TEXT: - format = &format_text; + format = sprinter_text_create (ctx, stdout); break; case NOTMUCH_FORMAT_JSON: - format = &format_json; + format = sprinter_json_create (ctx, stdout); break; + default: + /* this should never happen */ + INTERNAL_ERROR("no output format selected"); } config = notmuch_config_open (ctx, NULL, NULL); @@ -546,5 +416,7 @@ notmuch_search_command (void *ctx, int argc, char *argv[]) notmuch_query_destroy (query); notmuch_database_destroy (notmuch); + talloc_free (format); + return ret; } diff --git a/test/json b/test/json index 6439788..337b3f5 100755 --- a/test/json +++ b/test/json @@ -9,15 +9,16 @@ test_expect_equal "$output" "[[[{\"id\": \"${gen_msg_id}\", \"match\": true, \"e 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) +output=$(notmuch search --format=json "json-search-message" | notmuch_json_show_sanitize | notmuch_search_sanitize) test_expect_equal "$output" "[{\"thread\": \"XXX\", -\"timestamp\": 946728000, -\"date_relative\": \"2000-01-01\", -\"matched\": 1, -\"total\": 1, -\"authors\": \"Notmuch Test Suite\", -\"subject\": \"json-search-subject\", -\"tags\": [\"inbox\", \"unread\"]}]" + \"timestamp\": 946728000, + \"date_relative\": \"2000-01-01\", + \"matched\": 1, + \"total\": 1, + \"authors\": \"Notmuch Test Suite\", + \"subject\": \"json-search-subject\", + \"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\"" @@ -39,14 +40,15 @@ test_expect_equal "$output" "[[[{\"id\": \"$id\", \"match\": true, \"excluded\": 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) +output=$(notmuch search --format=json "jsön-search-méssage" | notmuch_json_show_sanitize | notmuch_search_sanitize) test_expect_equal "$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\", -\"tags\": [\"inbox\", \"unread\"]}]" + \"timestamp\": 946728000, + \"date_relative\": \"2000-01-01\", + \"matched\": 1, + \"total\": 1, + \"authors\": \"Notmuch Test Suite\", + \"subject\": \"json-search-utf8-body-sübjéct\", + \"tags\": [\"inbox\", + \"unread\"]}]" test_done -- cgit v1.2.3 From 3ea77f9f1fbc4781da29d9eee2e92e6c143e7a4a Mon Sep 17 00:00:00 2001 From: Mark Walters Date: Tue, 24 Jul 2012 19:23:28 +0100 Subject: test: add tests for the new --body=true|false option --- test/json | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'test') diff --git a/test/json b/test/json index 337b3f5..831e105 100755 --- a/test/json +++ b/test/json @@ -7,6 +7,15 @@ add_message "[subject]=\"json-show-subject\"" "[date]=\"Sat, 01 Jan 2000 12:00:0 output=$(notmuch show --format=json "json-show-message") test_expect_equal "$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 \", \"To\": \"Notmuch Test Suite \", \"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 "$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 \", \"To\": \"Notmuch Test Suite \", \"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 "$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 \", \"To\": \"Notmuch Test Suite \", \"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_json_show_sanitize | notmuch_search_sanitize) -- cgit v1.2.3 From 8a745d310f966194e82f12f6453f05cc877379d6 Mon Sep 17 00:00:00 2001 From: David Bremner Date: Thu, 2 Aug 2012 09:27:26 -0300 Subject: build system: remove directories created by tests in "make clean" These extra directories cause problems for building on Debian twice in a row. In order to remove directories, we need to us "rm -rf" instead of "rm -f". So now we should be extra careful what we add to the variable CLEAN. --- Makefile.local | 2 +- test/Makefile.local | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'test') diff --git a/Makefile.local b/Makefile.local index 296995d..6d6896a 100644 --- a/Makefile.local +++ b/Makefile.local @@ -265,7 +265,7 @@ quiet ?= $($(shell echo $1 | sed -e s'/ .*//')) .PHONY : clean clean: - rm -f $(CLEAN); rm -rf .deps + rm -rf $(CLEAN); rm -rf .deps # We don't (yet) have any distributed files not in the upstream repository. # So distclean is currently identical to clean. diff --git a/test/Makefile.local b/test/Makefile.local index 4a6a4b1..c7f1435 100644 --- a/test/Makefile.local +++ b/test/Makefile.local @@ -31,4 +31,5 @@ check: test SRCS := $(SRCS) $(smtp_dummy_srcs) CLEAN := $(CLEAN) $(dir)/smtp-dummy $(dir)/smtp-dummy.o \ $(dir)/symbol-test $(dir)/symbol-test.o \ - $(dir)/arg-test $(dir)/arg-test.o + $(dir)/arg-test $(dir)/arg-test.o \ + $(dir)/corpus.mail $(dir)/test-results $(dir)/tmp.* -- cgit v1.2.3 From a34bb1f9fad7c547eec5c254ce8274f190491186 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Thu, 2 Aug 2012 21:14:47 -0400 Subject: test: Uniformly canonicalize actual and expected JSON Previously, we used a variety of ad-hoc canonicalizations for JSON output in the test suite, but were ultimately very sensitive to JSON irrelevancies such as whitespace. This introduces a new test comparison function, test_expect_equal_json, that first pretty-prints *both* the actual and expected JSON and the compares the result. The current implementation of this simply uses Python's json.tool to perform pretty-printing (with a fallback to the identity function if parsing fails). However, since the interface it introduces is semantically high-level, we could swap in other mechanisms in the future, such as another pretty-printer or something that does not re-order object keys (if we decide that we care about that). In general, this patch does not remove the existing ad-hoc canonicalization because it does no harm. We do have to remove the newline-after-comma rule from notmuch_json_show_sanitize and filter_show_json because it results in invalid JSON that cannot be pretty-printed. Most of this patch simply replaces test_expect_equal and test_expect_equal_file with test_expect_equal_json. It changes the expected JSON in a few places where sanitizers had placed newlines after commas inside strings. --- test/crypto | 37 +++++++++++++++---------------------- test/json | 14 +++++++------- test/maildir-sync | 11 ++++------- test/multipart | 34 +++++++++++++++------------------- test/search-output | 2 +- test/test-lib.sh | 17 +++++++++++++---- 6 files changed, 55 insertions(+), 60 deletions(-) (limited to 'test') diff --git a/test/crypto b/test/crypto index be752b1..5dd14c4 100755 --- a/test/crypto +++ b/test/crypto @@ -51,8 +51,7 @@ expected='[[[{"id": "XXXXX", "headers": {"Subject": "test signed message 001", "From": "Notmuch Test Suite ", "To": "test_suite@notmuchmail.org", - "Date": "Sat, - 01 Jan 2000 12:00:00 +0000"}, + "Date": "Sat, 01 Jan 2000 12:00:00 +0000"}, "body": [{"id": 1, "sigstatus": [{"status": "good", "fingerprint": "'$FINGERPRINT'", @@ -64,7 +63,7 @@ expected='[[[{"id": "XXXXX", {"id": 3, "content-type": "application/pgp-signature"}]}]}, []]]]' -test_expect_equal \ +test_expect_equal_json \ "$output" \ "$expected" @@ -85,8 +84,7 @@ expected='[[[{"id": "XXXXX", "headers": {"Subject": "test signed message 001", "From": "Notmuch Test Suite ", "To": "test_suite@notmuchmail.org", - "Date": "Sat, - 01 Jan 2000 12:00:00 +0000"}, + "Date": "Sat, 01 Jan 2000 12:00:00 +0000"}, "body": [{"id": 1, "sigstatus": [{"status": "good", "fingerprint": "'$FINGERPRINT'", @@ -99,7 +97,7 @@ expected='[[[{"id": "XXXXX", {"id": 3, "content-type": "application/pgp-signature"}]}]}, []]]]' -test_expect_equal \ +test_expect_equal_json \ "$output" \ "$expected" @@ -119,8 +117,7 @@ expected='[[[{"id": "XXXXX", "headers": {"Subject": "test signed message 001", "From": "Notmuch Test Suite ", "To": "test_suite@notmuchmail.org", - "Date": "Sat, - 01 Jan 2000 12:00:00 +0000"}, + "Date": "Sat, 01 Jan 2000 12:00:00 +0000"}, "body": [{"id": 1, "sigstatus": [{"status": "error", "keyid": "'$(echo $FINGERPRINT | cut -c 25-)'", @@ -132,7 +129,7 @@ expected='[[[{"id": "XXXXX", {"id": 3, "content-type": "application/pgp-signature"}]}]}, []]]]' -test_expect_equal \ +test_expect_equal_json \ "$output" \ "$expected" mv "${GNUPGHOME}"{.bak,} @@ -193,8 +190,7 @@ expected='[[[{"id": "XXXXX", "headers": {"Subject": "test encrypted message 001", "From": "Notmuch Test Suite ", "To": "test_suite@notmuchmail.org", - "Date": "Sat, - 01 Jan 2000 12:00:00 +0000"}, + "Date": "Sat, 01 Jan 2000 12:00:00 +0000"}, "body": [{"id": 1, "encstatus": [{"status": "good"}], "sigstatus": [], @@ -210,7 +206,7 @@ expected='[[[{"id": "XXXXX", "content-type": "application/octet-stream", "filename": "TESTATTACHMENT"}]}]}]}, []]]]' -test_expect_equal \ +test_expect_equal_json \ "$output" \ "$expected" @@ -221,7 +217,7 @@ output=$(notmuch show --format=json --part=4 --decrypt subject:"test encrypted m expected='{"id": 4, "content-type": "text/plain", "content": "This is a test encrypted message.\n"}' -test_expect_equal \ +test_expect_equal_json \ "$output" \ "$expected" @@ -248,8 +244,7 @@ expected='[[[{"id": "XXXXX", "headers": {"Subject": "test encrypted message 001", "From": "Notmuch Test Suite ", "To": "test_suite@notmuchmail.org", - "Date": "Sat, - 01 Jan 2000 12:00:00 +0000"}, + "Date": "Sat, 01 Jan 2000 12:00:00 +0000"}, "body": [{"id": 1, "encstatus": [{"status": "bad"}], "content-type": "multipart/encrypted", @@ -258,7 +253,7 @@ expected='[[[{"id": "XXXXX", {"id": 3, "content-type": "application/octet-stream"}]}]}, []]]]' -test_expect_equal \ +test_expect_equal_json \ "$output" \ "$expected" mv "${GNUPGHOME}"{.bak,} @@ -283,8 +278,7 @@ expected='[[[{"id": "XXXXX", "headers": {"Subject": "test encrypted message 002", "From": "Notmuch Test Suite ", "To": "test_suite@notmuchmail.org", - "Date": "Sat, - 01 Jan 2000 12:00:00 +0000"}, + "Date": "Sat, 01 Jan 2000 12:00:00 +0000"}, "body": [{"id": 1, "encstatus": [{"status": "good"}], "sigstatus": [{"status": "good", @@ -298,7 +292,7 @@ expected='[[[{"id": "XXXXX", "content-type": "text/plain", "content": "This is another test encrypted message.\n"}]}]}, []]]]' -test_expect_equal \ +test_expect_equal_json \ "$output" \ "$expected" @@ -338,8 +332,7 @@ expected='[[[{"id": "XXXXX", "headers": {"Subject": "test signed message 001", "From": "Notmuch Test Suite ", "To": "test_suite@notmuchmail.org", - "Date": "Sat, - 01 Jan 2000 12:00:00 +0000"}, + "Date": "Sat, 01 Jan 2000 12:00:00 +0000"}, "body": [{"id": 1, "sigstatus": [{"status": "error", "keyid": "6D92612D94E46381", @@ -351,7 +344,7 @@ expected='[[[{"id": "XXXXX", {"id": 3, "content-type": "application/pgp-signature"}]}]}, []]]]' -test_expect_equal \ +test_expect_equal_json \ "$output" \ "$expected" diff --git a/test/json b/test/json index 831e105..d86ee46 100755 --- a/test/json +++ b/test/json @@ -5,21 +5,21 @@ test_description="--format=json output" test_begin_subtest "Show message: json" add_message "[subject]=\"json-show-subject\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[body]=\"json-show-message\"" output=$(notmuch show --format=json "json-show-message") -test_expect_equal "$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 \", \"To\": \"Notmuch Test Suite \", \"Date\": \"Sat, 01 Jan 2000 12:00:00 +0000\"}, \"body\": [{\"id\": 1, \"content-type\": \"text/plain\", \"content\": \"json-show-message\n\"}]}, []]]]" +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 \", \"To\": \"Notmuch Test Suite \", \"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 "$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 \", \"To\": \"Notmuch Test Suite \", \"Date\": \"Sat, 01 Jan 2000 12:00:00 +0000\"}, \"body\": [{\"id\": 1, \"content-type\": \"text/plain\", \"content\": \"json-show-message\n\"}]}, []]]]" +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 \", \"To\": \"Notmuch Test Suite \", \"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 "$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 \", \"To\": \"Notmuch Test Suite \", \"Date\": \"Sat, 01 Jan 2000 12:00:00 +0000\"}}, []]]]" +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 \", \"To\": \"Notmuch Test Suite \", \"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_json_show_sanitize | notmuch_search_sanitize) -test_expect_equal "$output" "[{\"thread\": \"XXX\", +test_expect_equal_json "$output" "[{\"thread\": \"XXX\", \"timestamp\": 946728000, \"date_relative\": \"2000-01-01\", \"matched\": 1, @@ -32,7 +32,7 @@ test_expect_equal "$output" "[{\"thread\": \"XXX\", 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 "$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 \", \"To\": \"Notmuch Test Suite \", \"Date\": \"Sat, 01 Jan 2000 12:00:00 +0000\"}, \"body\": [{\"id\": 1, \"content-type\": \"text/plain\", \"content\": \"jsön-show-méssage\n\"}]}, []]]]" +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 \", \"To\": \"Notmuch Test Suite \", \"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' @@ -45,12 +45,12 @@ emacs_deliver_message \ (insert \"Message-ID: <$id>\n\")" output=$(notmuch show --format=json "id:$id") filename=$(notmuch search --output=files "id:$id") -test_expect_equal "$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 \", \"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\"}]}]}, []]]]" +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 \", \"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\"}]}]}, []]]]" 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_json_show_sanitize | notmuch_search_sanitize) -test_expect_equal "$output" "[{\"thread\": \"XXX\", +test_expect_equal_json "$output" "[{\"thread\": \"XXX\", \"timestamp\": 946728000, \"date_relative\": \"2000-01-01\", \"matched\": 1, diff --git a/test/maildir-sync b/test/maildir-sync index 01348d3..b748d04 100755 --- a/test/maildir-sync +++ b/test/maildir-sync @@ -4,11 +4,9 @@ test_description="maildir synchronization" . ./test-lib.sh -# Much easier to examine differences if the "notmuch show -# --format=json" output includes some newlines. Also, need to avoid -# including the local value of MAIL_DIR in the result. +# Avoid including the local value of MAIL_DIR in the result. filter_show_json() { - sed -e 's/, /,\n/g' | sed -e "s|${MAIL_DIR}/|MAIL_DIR/|" + sed -e "s|${MAIL_DIR}/|MAIL_DIR/|" echo } @@ -44,7 +42,7 @@ 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} | filter_show_json) -test_expect_equal "$output" '[[[{"id": "adding-replied-tag@notmuch-test-suite", +test_expect_equal_json "$output" '[[[{"id": "adding-replied-tag@notmuch-test-suite", "match": true, "excluded": false, "filename": "MAIL_DIR/cur/adding-replied-tag:2,RS", @@ -54,8 +52,7 @@ test_expect_equal "$output" '[[[{"id": "adding-replied-tag@notmuch-test-suite", "headers": {"Subject": "Adding replied tag", "From": "Notmuch Test Suite ", "To": "Notmuch Test Suite ", -"Date": "Fri, -05 Jan 2001 15:43:57 +0000"}, +"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"}]}, diff --git a/test/multipart b/test/multipart index 72d3927..3ccf27f 100755 --- a/test/multipart +++ b/test/multipart @@ -334,7 +334,7 @@ cat <EXPECTED {"id": 8, "content-type": "text/plain", "content": "And this message is signed.\n\n-Carl\n"}]}, {"id": 9, "content-type": "application/pgp-signature"}]}]} EOF -test_expect_equal_file OUTPUT EXPECTED +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' | sed 's|{"id":|\n{"id":|g' >OUTPUT @@ -351,7 +351,7 @@ cat <EXPECTED {"id": 8, "content-type": "text/plain", "content": "And this message is signed.\n\n-Carl\n"}]}, {"id": 9, "content-type": "application/pgp-signature"}]} EOF -test_expect_equal_file OUTPUT EXPECTED +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' | sed 's|{"id":|\n{"id":|g' >OUTPUT @@ -366,7 +366,7 @@ cat <EXPECTED {"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_file OUTPUT EXPECTED +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' | sed 's|{"id":|\n{"id":|g' >OUTPUT @@ -378,7 +378,7 @@ cat <EXPECTED {"id": 5, "content-type": "text/html"}, {"id": 6, "content-type": "text/plain", "content": "This is an embedded message, with a multipart/alternative part.\n"}]}]}]} EOF -test_expect_equal_file OUTPUT EXPECTED +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' | sed 's|{"id":|\n{"id":|g' >OUTPUT @@ -389,7 +389,7 @@ cat <EXPECTED {"id": 5, "content-type": "text/html"}, {"id": 6, "content-type": "text/plain", "content": "This is an embedded message, with a multipart/alternative part.\n"}]} EOF -test_expect_equal_file OUTPUT EXPECTED +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' | sed 's|{"id":|\n{"id":|g' >OUTPUT @@ -398,7 +398,7 @@ cat <EXPECTED {"id": 5, "content-type": "text/html"} EOF -test_expect_equal_file OUTPUT EXPECTED +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' | sed 's|{"id":|\n{"id":|g' >OUTPUT @@ -407,7 +407,7 @@ cat <EXPECTED {"id": 6, "content-type": "text/plain", "content": "This is an embedded message, with a multipart/alternative part.\n"} EOF -test_expect_equal_file OUTPUT EXPECTED +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' | sed 's|{"id":|\n{"id":|g' >OUTPUT @@ -416,7 +416,7 @@ cat <EXPECTED {"id": 7, "content-type": "text/plain", "filename": "attachment", "content": "This is a text attachment.\n"} EOF -test_expect_equal_file OUTPUT EXPECTED +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' | sed 's|{"id":|\n{"id":|g' >OUTPUT @@ -425,7 +425,7 @@ cat <EXPECTED {"id": 8, "content-type": "text/plain", "content": "And this message is signed.\n\n-Carl\n"} EOF -test_expect_equal_file OUTPUT EXPECTED +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' | sed 's|{"id":|\n{"id":|g' >OUTPUT @@ -434,7 +434,7 @@ cat <EXPECTED {"id": 9, "content-type": "application/pgp-signature"} EOF -test_expect_equal_file OUTPUT EXPECTED +test_expect_equal_json "$(cat OUTPUT)" "$(cat EXPECTED)" test_expect_success \ "--format=json --part=10, no part, expect error" \ @@ -617,8 +617,7 @@ notmuch reply --format=json 'id:87liy5ap00.fsf@yoom.home.cworth.org' | notmuch_j cat <EXPECTED {"reply-headers": {"Subject": "Re: Multipart message", "From": "Notmuch Test Suite ", - "To": "Carl Worth , - cworth@cworth.org", + "To": "Carl Worth , cworth@cworth.org", "In-reply-to": "<87liy5ap00.fsf@yoom.home.cworth.org>", "References": " <87liy5ap00.fsf@yoom.home.cworth.org>"}, "original": {"id": "XXXXX", @@ -631,8 +630,7 @@ cat <EXPECTED "headers": {"Subject": "Multipart message", "From": "Carl Worth ", "To": "cworth@cworth.org", - "Date": "Fri, - 05 Jan 2001 15:43:57 +0000"}, + "Date": "Fri, 05 Jan 2001 15:43:57 +0000"}, "body": [{"id": 1, "content-type": "multipart/signed", "content": [{"id": 2, @@ -642,16 +640,14 @@ cat <EXPECTED "content": [{"headers": {"Subject": "html message", "From": "Carl Worth ", "To": "cworth@cworth.org", - "Date": "Fri, - 05 Jan 2001 15:42:57 +0000"}, + "Date": "Fri, 05 Jan 2001 15:42:57 +0000"}, "body": [{"id": 4, "content-type": "multipart/alternative", "content": [{"id": 5, "content-type": "text/html"}, {"id": 6, "content-type": "text/plain", - "content": "This is an embedded message, - with a multipart/alternative part.\n"}]}]}]}, + "content": "This is an embedded message, with a multipart/alternative part.\n"}]}]}]}, {"id": 7, "content-type": "text/plain", "filename": "YYYYY", @@ -662,7 +658,7 @@ cat <EXPECTED {"id": 9, "content-type": "application/pgp-signature"}]}]}} EOF -test_expect_equal_file OUTPUT EXPECTED +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 diff --git a/test/search-output b/test/search-output index 8b57a43..c2a87eb 100755 --- a/test/search-output +++ b/test/search-output @@ -62,7 +62,7 @@ cat <EXPECTED "THREADID", "THREADID"] EOF -test_expect_equal_file OUTPUT EXPECTED +test_expect_equal_json "$(cat OUTPUT)" "$(cat EXPECTED)" test_begin_subtest "--output=messages" notmuch search --output=messages '*' >OUTPUT diff --git a/test/test-lib.sh b/test/test-lib.sh index 06aaea2..791d2dc 100644 --- a/test/test-lib.sh +++ b/test/test-lib.sh @@ -512,6 +512,16 @@ test_expect_equal_file () fi } +# Like test_expect_equal, but arguments are JSON expressions to be +# canonicalized before diff'ing. If an argument cannot be parsed, it +# is used unchanged so that there's something to diff against. +test_expect_equal_json () { + output=$(echo "$1" | python -mjson.tool || echo "$1") + expected=$(echo "$2" | python -mjson.tool || echo "$2") + shift 2 + test_expect_equal "$output" "$expected" "$@" +} + test_emacs_expect_t () { test "$#" = 2 && { prereq=$1; shift; } || prereq= test "$#" = 1 || @@ -565,10 +575,9 @@ notmuch_show_sanitize_all () notmuch_json_show_sanitize () { - sed -e 's|, |,\n |g' | \ - sed \ - -e 's|"id": "[^"]*",|"id": "XXXXX",|' \ - -e 's|"filename": "[^"]*",|"filename": "YYYYY",|' + sed \ + -e 's|"id": "[^"]*",|"id": "XXXXX",|g' \ + -e 's|"filename": "[^"]*",|"filename": "YYYYY",|g' } # End of notmuch helper functions -- cgit v1.2.3 From 624d1897ce70fde8a41f2ea245db2a5e27f16ce1 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Thu, 2 Aug 2012 21:14:48 -0400 Subject: test: Remove unnecessary JSON canonicalization Format canonicalization of JSON output is no longer necessary, so remove it. Value canonicalization (e.g., normalizing thread IDs) is still necessary, so all of the sanitization functions remain. --- test/json | 4 ++-- test/maildir-sync | 1 - test/multipart | 40 ++++++++++------------------------------ 3 files changed, 12 insertions(+), 33 deletions(-) (limited to 'test') diff --git a/test/json b/test/json index d86ee46..ac8fa8e 100755 --- a/test/json +++ b/test/json @@ -18,7 +18,7 @@ test_expect_equal_json "$output" "[[[{\"id\": \"${gen_msg_id}\", \"match\": true 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_json_show_sanitize | notmuch_search_sanitize) +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\", @@ -49,7 +49,7 @@ test_expect_equal_json "$output" "[[[{\"id\": \"$id\", \"match\": true, \"exclud 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_json_show_sanitize | notmuch_search_sanitize) +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\", diff --git a/test/maildir-sync b/test/maildir-sync index b748d04..cd7d241 100755 --- a/test/maildir-sync +++ b/test/maildir-sync @@ -7,7 +7,6 @@ test_description="maildir synchronization" # Avoid including the local value of MAIL_DIR in the result. filter_show_json() { sed -e "s|${MAIL_DIR}/|MAIL_DIR/|" - echo } # Create the expected maildir structure diff --git a/test/multipart b/test/multipart index 3ccf27f..0527f84 100755 --- a/test/multipart +++ b/test/multipart @@ -319,10 +319,8 @@ test_expect_success \ "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' | sed 's|{"id":|\n{"id":|g' >OUTPUT -echo >>OUTPUT # expect *no* newline at end of output +notmuch show --format=json --part=0 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT cat <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 ", "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": [ @@ -337,10 +335,8 @@ 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' | sed 's|{"id":|\n{"id":|g' >OUTPUT -echo >>OUTPUT # expect *no* newline at end of output +notmuch show --format=json --part=1 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT cat <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 ", "To": "cworth@cworth.org", "Date": "Fri, 05 Jan 2001 15:42:57 +0000"}, "body": [ @@ -354,10 +350,8 @@ 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' | sed 's|{"id":|\n{"id":|g' >OUTPUT -echo >>OUTPUT # expect *no* newline at end of output +notmuch show --format=json --part=2 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT cat <EXPECTED - {"id": 2, "content-type": "multipart/mixed", "content": [ {"id": 3, "content-type": "message/rfc822", "content": [{"headers": {"Subject": "html message", "From": "Carl Worth ", "To": "cworth@cworth.org", "Date": "Fri, 05 Jan 2001 15:42:57 +0000"}, "body": [ {"id": 4, "content-type": "multipart/alternative", "content": [ @@ -369,10 +363,8 @@ 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' | sed 's|{"id":|\n{"id":|g' >OUTPUT -echo >>OUTPUT # expect *no* newline at end of output +notmuch show --format=json --part=3 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT cat <EXPECTED - {"id": 3, "content-type": "message/rfc822", "content": [{"headers": {"Subject": "html message", "From": "Carl Worth ", "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"}, @@ -381,10 +373,8 @@ 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' | sed 's|{"id":|\n{"id":|g' >OUTPUT -echo >>OUTPUT # expect *no* newline at end of output +notmuch show --format=json --part=4 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT cat <EXPECTED - {"id": 4, "content-type": "multipart/alternative", "content": [ {"id": 5, "content-type": "text/html"}, {"id": 6, "content-type": "text/plain", "content": "This is an embedded message, with a multipart/alternative part.\n"}]} @@ -392,46 +382,36 @@ 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' | sed 's|{"id":|\n{"id":|g' >OUTPUT -echo >>OUTPUT # expect *no* newline at end of output +notmuch show --format=json --part=5 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT cat <EXPECTED - {"id": 5, "content-type": "text/html"} 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' | sed 's|{"id":|\n{"id":|g' >OUTPUT -echo >>OUTPUT # expect *no* newline at end of output +notmuch show --format=json --part=6 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT cat <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' | sed 's|{"id":|\n{"id":|g' >OUTPUT -echo >>OUTPUT # expect *no* newline at end of output +notmuch show --format=json --part=7 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT cat <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' | sed 's|{"id":|\n{"id":|g' >OUTPUT -echo >>OUTPUT # expect *no* newline at end of output +notmuch show --format=json --part=8 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT cat <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' | sed 's|{"id":|\n{"id":|g' >OUTPUT -echo >>OUTPUT # expect *no* newline at end of output +notmuch show --format=json --part=9 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT cat <EXPECTED - {"id": 9, "content-type": "application/pgp-signature"} EOF test_expect_equal_json "$(cat OUTPUT)" "$(cat EXPECTED)" -- cgit v1.2.3 From 760e17488e6b11299f2971cf879b109b84816d14 Mon Sep 17 00:00:00 2001 From: David Bremner Date: Fri, 3 Aug 2012 23:23:11 -0300 Subject: notmuch-dump: remove deprecated positional argument for output file The syntax --output=filename is a smaller change than deleting the output argument completely, and conceivably useful e.g. when running notmuch under a debugger. --- man/man1/notmuch-dump.1 | 5 ++--- notmuch-dump.c | 3 +-- test/dump-restore | 20 ++++++++------------ test/maildir-sync | 2 +- 4 files changed, 12 insertions(+), 18 deletions(-) (limited to 'test') diff --git a/man/man1/notmuch-dump.1 b/man/man1/notmuch-dump.1 index 64abf01..5d1e197 100644 --- a/man/man1/notmuch-dump.1 +++ b/man/man1/notmuch-dump.1 @@ -5,15 +5,14 @@ notmuch-dump \- creates a plain-text dump of the tags of each message .SH SYNOPSIS .B "notmuch dump" -.RI "[ <" filename "> ] [--]" +.RI "[ --output=<" filename "> ] [--]" .RI "[ <" search-term ">...]" .SH DESCRIPTION Dump tags for messages matching the given search terms. -Output is to the given filename, if any, or to stdout. Note that -using the filename argument is deprecated. +Output is to the given filename, if any, or to stdout. These tags are the only data in the notmuch database that can't be recreated from the messages themselves. The output of notmuch dump is diff --git a/notmuch-dump.c b/notmuch-dump.c index 3743214..d8186fb 100644 --- a/notmuch-dump.c +++ b/notmuch-dump.c @@ -44,7 +44,7 @@ notmuch_dump_command (unused (void *ctx), int argc, char *argv[]) int opt_index; notmuch_opt_desc_t options[] = { - { NOTMUCH_OPT_POSITION, &output_file_name, 0, 0, 0 }, + { NOTMUCH_OPT_STRING, &output_file_name, "output", 'o', 0 }, { 0, 0, 0, 0, 0 } }; @@ -56,7 +56,6 @@ notmuch_dump_command (unused (void *ctx), int argc, char *argv[]) } if (output_file_name) { - fprintf (stderr, "Warning: the output file argument of dump is deprecated.\n"); output = fopen (output_file_name, "w"); if (output == NULL) { fprintf (stderr, "Error opening %s for writing: %s\n", diff --git a/test/dump-restore b/test/dump-restore index 439e998..c7801cf 100755 --- a/test/dump-restore +++ b/test/dump-restore @@ -53,16 +53,12 @@ test_expect_success 'Restore with nothing to do, III' \ test_expect_success 'Invalid restore invocation' \ 'test_must_fail notmuch restore dump.expected another_one' -test_begin_subtest "dump outfile" -notmuch dump dump-outfile.actual +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 outfile # deprecated" -test_expect_equal "Warning: the output file argument of dump is deprecated."\ - "$(notmuch dump /dev/null 2>&1)" - -test_begin_subtest "dump outfile --" -notmuch dump dump-1-arg-dash.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 @@ -74,12 +70,12 @@ 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 outfile from:cworth" -notmuch dump dump-outfile-cworth.actual from:cworth +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 outfile -- from:cworth" -notmuch dump dump-outfile-dash-inbox.actual -- from:cworth +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_done diff --git a/test/maildir-sync b/test/maildir-sync index cd7d241..0914fa5 100755 --- a/test/maildir-sync +++ b/test/maildir-sync @@ -124,7 +124,7 @@ 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 dump.txt +notmuch dump --output=dump.txt NOTMUCH_NEW >/dev/null notmuch restore dump.txt output=$(ls $MAIL_DIR/cur) -- cgit v1.2.3 From 19c824c3fd7be29a2257cdd530ee23074c978d63 Mon Sep 17 00:00:00 2001 From: David Bremner Date: Sat, 4 Aug 2012 09:55:45 -0300 Subject: notmuch-restore: replace positional argument for input with option Since notmuch dump doesn't use positional arguments anymore, it seems better to be consistent. --- man/man1/notmuch-restore.1 | 2 +- notmuch-restore.c | 2 +- test/dump-restore | 8 ++++---- test/maildir-sync | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) (limited to 'test') diff --git a/man/man1/notmuch-restore.1 b/man/man1/notmuch-restore.1 index 18281c7..d0d50dd 100644 --- a/man/man1/notmuch-restore.1 +++ b/man/man1/notmuch-restore.1 @@ -6,7 +6,7 @@ notmuch-restore \- restores the tags from the given file (see notmuch dump) .B "notmuch restore" .RB [ "--accumulate" ] -.RI "[ <" filename "> ]" +.RI "[ --input=<" filename "> ]" .SH DESCRIPTION diff --git a/notmuch-restore.c b/notmuch-restore.c index 4f4096e..08d5adc 100644 --- a/notmuch-restore.c +++ b/notmuch-restore.c @@ -122,7 +122,7 @@ notmuch_restore_command (unused (void *ctx), int argc, char *argv[]) synchronize_flags = notmuch_config_get_maildir_synchronize_flags (config); notmuch_opt_desc_t options[] = { - { NOTMUCH_OPT_POSITION, &input_file_name, 0, 0, 0 }, + { NOTMUCH_OPT_STRING, &input_file_name, "input", 'i', 0 }, { NOTMUCH_OPT_BOOLEAN, &accumulate, "accumulate", 'a', 0 }, { 0, 0, 0, 0, 0 } }; diff --git a/test/dump-restore b/test/dump-restore index c7801cf..f25f7cf 100755 --- a/test/dump-restore +++ b/test/dump-restore @@ -19,7 +19,7 @@ test_expect_success 'Dumping all tags II' \ test_expect_success 'Clearing all tags' \ 'sed -e "s/(\([^(]*\))$/()/" < dump.expected > clear.expected && - notmuch restore clear.expected && + notmuch restore --input=clear.expected && notmuch dump > clear.actual && test_cmp clear.expected clear.actual' @@ -30,7 +30,7 @@ test_expect_success 'Accumulate original tags' \ test_cmp dump-ABC_DEF.expected dump.actual' test_expect_success 'Restoring original tags' \ - 'notmuch restore dump.expected && + 'notmuch restore --input=dump.expected && notmuch dump > dump.actual && test_cmp dump.expected dump.actual' @@ -40,7 +40,7 @@ test_expect_success 'Restore with nothing to do' \ test_cmp dump.expected dump.actual' test_expect_success 'Restore with nothing to do, II' \ - 'notmuch restore --accumulate dump.expected && + 'notmuch restore --accumulate --input=dump.expected && notmuch dump > dump.actual && test_cmp dump.expected dump.actual' @@ -51,7 +51,7 @@ test_expect_success 'Restore with nothing to do, III' \ # notmuch restore currently only considers the first argument. test_expect_success 'Invalid restore invocation' \ - 'test_must_fail notmuch restore dump.expected another_one' + 'test_must_fail notmuch restore --input=dump.expected another_one' test_begin_subtest "dump --output=outfile" notmuch dump --output=dump-outfile.actual diff --git a/test/maildir-sync b/test/maildir-sync index 0914fa5..0fc742a 100755 --- a/test/maildir-sync +++ b/test/maildir-sync @@ -126,7 +126,7 @@ 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 dump.txt +notmuch restore --input=dump.txt output=$(ls $MAIL_DIR/cur) test_expect_equal "$output" "$expected" -- cgit v1.2.3