diff options
| author | Daniel Kahn Gillmor <dkg@fifthhorseman.net> | 2018-02-04 15:33:34 -0500 |
|---|---|---|
| committer | Daniel Kahn Gillmor <dkg@fifthhorseman.net> | 2018-02-04 15:33:34 -0500 |
| commit | d9be1028d47cb7e98b474df420858a690798810b (patch) | |
| tree | fb37f83ca098129a5301ef141dc6a5007a0972a9 /test | |
| parent | a8fb877ad7e960d69ec10887ff79e24bb99c587c (diff) | |
| parent | 3c4e64d976eb561ac5157df1bbe5882e3e65b583 (diff) | |
Merge tag 'debian/0.26-1' into debian/stretch-backports
notmuch Debian 0.26-1 upload (same as 0.26)
Diffstat (limited to 'test')
92 files changed, 1608 insertions, 655 deletions
diff --git a/test/.gitignore b/test/.gitignore index 0579feef..73fe7e24 100644 --- a/test/.gitignore +++ b/test/.gitignore @@ -1,11 +1,11 @@ -arg-test -corpus.mail -hex-xcode -parse-time -random-corpus -smtp-dummy -symbol-test -make-db-version -test-results -ghost-report -tmp.* +/arg-test +/corpora.mail +/hex-xcode +/parse-time +/random-corpus +/smtp-dummy +/symbol-test +/make-db-version +/test-results +/ghost-report +/tmp.* diff --git a/test/Makefile.local b/test/Makefile.local index 0df72c92..1a0ab813 100644 --- a/test/Makefile.local +++ b/test/Makefile.local @@ -62,13 +62,13 @@ test-binaries: $(TEST_BINARIES) test: all test-binaries ifeq ($V,) @echo 'Use "$(MAKE) V=1" to see the details for passing and known broken tests.' - @env NOTMUCH_TEST_QUIET=1 ${test_src_dir}/notmuch-test $(OPTIONS) + @env NOTMUCH_TEST_QUIET=1 $(NOTMUCH_SRCDIR)/$(test_src_dir)/notmuch-test $(OPTIONS) else # The user has explicitly enabled quiet execution. ifeq ($V,0) - @env NOTMUCH_TEST_QUIET=1 ${test_src_dir}/notmuch-test $(OPTIONS) + @env NOTMUCH_TEST_QUIET=1 $(NOTMUCH_SRCDIR)/$(test_src_dir)/notmuch-test $(OPTIONS) else - @${test_src_dir}/notmuch-test $(OPTIONS) + @$(NOTMUCH_SRCDIR)/$(test_src_dir)/notmuch-test $(OPTIONS) endif endif diff --git a/test/README b/test/README index 8e06f442..b378c3ff 100644 --- a/test/README +++ b/test/README @@ -80,15 +80,6 @@ The following command-line options are available when running tests: As the names depend on the tests' file names, it is safe to run the tests with this option in parallel. ---root=<dir>:: - This runs the testsuites specified under a separate directory. - However, caution is advised, as not all tests are maintained - with this relocation in mind, so some tests may behave - differently. - - Pointing this argument at a tmpfs filesystem can improve the - speed of the test suite for some users. - Certain tests require precomputed databases to complete. You can fetch these databases with diff --git a/test/T000-basic.sh b/test/T000-basic.sh index 36a7ca4c..7fbdcfa3 100755 --- a/test/T000-basic.sh +++ b/test/T000-basic.sh @@ -4,17 +4,7 @@ # test_description='the test framework itself.' - -################################################################ -# It appears that people try to run tests without building... - -if ! test -x ../notmuch -then - echo >&2 'You do not seem to have built notmuch yet.' - exit 1 -fi - -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 ################################################################ # Test harness @@ -23,8 +13,7 @@ test_expect_success ':' test_begin_subtest 'test runs if prerequisite is satisfied' test_set_prereq HAVEIT -haveit=no -test_expect_success 'test_have_prereq HAVEIT && haveit=yes' +test_expect_success 'test_have_prereq HAVEIT' test_begin_subtest 'tests clean up after themselves' clean=no @@ -43,19 +32,19 @@ fi test_begin_subtest 'failure to clean up causes the test to fail' test_expect_code 2 'test_when_finished "(exit 2)"' -EXPECTED=$TEST_DIRECTORY/test.expected-output +EXPECTED=$NOTMUCH_SRCDIR/test/test.expected-output suppress_diff_date() { sed -e 's/\(.*\-\-\- test-verbose\.4\.\expected\).*/\1/' \ -e 's/\(.*\+\+\+ test-verbose\.4\.\output\).*/\1/' } test_begin_subtest "Ensure that test output is suppressed unless the test fails" -output=$(cd $TEST_DIRECTORY; NOTMUCH_TEST_QUIET= ./test-verbose 2>&1 | suppress_diff_date) +output=$(cd $TEST_DIRECTORY; NOTMUCH_TEST_QUIET= $NOTMUCH_SRCDIR/test/test-verbose 2>&1 | suppress_diff_date) expected=$(cat $EXPECTED/test-verbose-no | suppress_diff_date) test_expect_equal "$output" "$expected" test_begin_subtest "Ensure that -v does not suppress test output" -output=$(cd $TEST_DIRECTORY; NOTMUCH_TEST_QUIET= ./test-verbose -v 2>&1 | suppress_diff_date) +output=$(cd $TEST_DIRECTORY; NOTMUCH_TEST_QUIET= $NOTMUCH_SRCDIR/test/test-verbose -v 2>&1 | suppress_diff_date) expected=$(cat $EXPECTED/test-verbose-yes | suppress_diff_date) # Do not include the results of test-verbose in totals rm $TEST_DIRECTORY/test-results/test-verbose diff --git a/test/T010-help-test.sh b/test/T010-help-test.sh index 0c833de2..da45d3ae 100755 --- a/test/T010-help-test.sh +++ b/test/T010-help-test.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash test_description="online help" -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 test_begin_subtest 'notmuch --help' test_expect_success 'notmuch --help' diff --git a/test/T020-compact.sh b/test/T020-compact.sh index a3d7380e..58cd2ba7 100755 --- a/test/T020-compact.sh +++ b/test/T020-compact.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash test_description='"notmuch compact"' -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 add_message '[subject]=One' add_message '[subject]=Two' diff --git a/test/T030-config.sh b/test/T030-config.sh index 35d757f6..e91c3659 100755 --- a/test/T030-config.sh +++ b/test/T030-config.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash test_description='"notmuch config"' -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 test_begin_subtest "Get string value" test_expect_equal "$(notmuch config get user.name)" "Notmuch Test Suite" diff --git a/test/T040-setup.sh b/test/T040-setup.sh index 998bd6e0..56efe1d5 100755 --- a/test/T040-setup.sh +++ b/test/T040-setup.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash test_description='"notmuch setup"' -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 test_begin_subtest "Notmuch new without a config suggests notmuch setup" output=$(notmuch --config=new-notmuch-config new 2>&1) diff --git a/test/T050-new.sh b/test/T050-new.sh index ffa303ef..cd522364 100755 --- a/test/T050-new.sh +++ b/test/T050-new.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash test_description='"notmuch new" in several variations' -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 test_begin_subtest "No new messages" output=$(NOTMUCH_NEW --debug) @@ -259,6 +259,28 @@ ln -s i_do_not_exist "${MAIL_DIR}"/broken_link output=$(NOTMUCH_NEW 2>&1) test_expect_equal "$output" "No new mail." +test_begin_subtest "Ignore files and directories specified in new.ignore (regexp)" +notmuch config set new.ignore ".git" "/^bro.*ink\$/" "/ignored.*file/" +output=$(NOTMUCH_NEW --debug 2>&1 | sort) +test_expect_equal "$output" \ +"(D) add_files, pass 1: explicitly ignoring ${MAIL_DIR}/.git +(D) add_files, pass 1: explicitly ignoring ${MAIL_DIR}/.ignored_hidden_file +(D) add_files, pass 1: explicitly ignoring ${MAIL_DIR}/broken_link +(D) add_files, pass 1: explicitly ignoring ${MAIL_DIR}/ignored_file +(D) add_files, pass 1: explicitly ignoring ${MAIL_DIR}/one/ignored_file +(D) add_files, pass 1: explicitly ignoring ${MAIL_DIR}/one/two/ignored_file +(D) add_files, pass 1: explicitly ignoring ${MAIL_DIR}/one/two/three/.git +(D) add_files, pass 1: explicitly ignoring ${MAIL_DIR}/one/two/three/ignored_file +(D) add_files, pass 2: explicitly ignoring ${MAIL_DIR}/.git +(D) add_files, pass 2: explicitly ignoring ${MAIL_DIR}/.ignored_hidden_file +(D) add_files, pass 2: explicitly ignoring ${MAIL_DIR}/broken_link +(D) add_files, pass 2: explicitly ignoring ${MAIL_DIR}/ignored_file +(D) add_files, pass 2: explicitly ignoring ${MAIL_DIR}/one/ignored_file +(D) add_files, pass 2: explicitly ignoring ${MAIL_DIR}/one/two/ignored_file +(D) add_files, pass 2: explicitly ignoring ${MAIL_DIR}/one/two/three/.git +(D) add_files, pass 2: explicitly ignoring ${MAIL_DIR}/one/two/three/ignored_file +No new mail." + test_begin_subtest "Quiet: No new mail." output=$(NOTMUCH_NEW --quiet) test_expect_equal "$output" "" @@ -309,7 +331,7 @@ cat <<EOF > notmuch-new-vanish.gdb set breakpoint pending on set logging file notmuch-new-vanish-gdb.log set logging on -break add_file +break notmuch_database_index_file commands shell rm -f ${MAIL_DIR}/vanish continue diff --git a/test/T060-count.sh b/test/T060-count.sh index 4751440e..0c0bf473 100755 --- a/test/T060-count.sh +++ b/test/T060-count.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash test_description='"notmuch count" for messages and threads' -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 add_email_corpus diff --git a/test/T070-insert.sh b/test/T070-insert.sh index 48f212ee..40519bb2 100755 --- a/test/T070-insert.sh +++ b/test/T070-insert.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash test_description='"notmuch insert"' -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 test_require_external_prereq gdb @@ -132,6 +132,20 @@ output=$(notmuch search --output=files path:Drafts/new) dirname=$(dirname "$output") test_expect_equal "$dirname" "$MAIL_DIR/Drafts/new" +test_begin_subtest "Insert message into top level folder" +gen_insert_msg +notmuch insert --folder="" < "$gen_msg_filename" +output=$(notmuch search --output=files id:${gen_msg_id}) +dirname=$(dirname "$output") +test_expect_equal "$dirname" "$MAIL_DIR/new" + +test_begin_subtest "Insert message into folder with trailing /" +gen_insert_msg +notmuch insert --folder=Drafts/ < "$gen_msg_filename" +output=$(notmuch search --output=files id:${gen_msg_id}) +dirname=$(dirname "$output") +test_expect_equal "$dirname" "$MAIL_DIR/Drafts/new" + test_begin_subtest "Insert message into folder, add/remove tags" gen_insert_msg notmuch insert --folder=Drafts +draft -unread < "$gen_msg_filename" @@ -193,7 +207,7 @@ cat <<EOF > index-file-$code.gdb set breakpoint pending on set logging file index-file-$code.log set logging on -break notmuch_database_add_message +break notmuch_database_index_file commands return NOTMUCH_STATUS_$code continue @@ -205,13 +219,13 @@ done gen_insert_msg for code in FILE_NOT_EMAIL READ_ONLY_DATABASE UPGRADE_REQUIRED PATH_ERROR; do - test_begin_subtest "EXIT_FAILURE when add_message returns $code" + test_begin_subtest "EXIT_FAILURE when index_file returns $code" test_expect_code 1 \ "${TEST_GDB} --batch-silent --return-child-result \ -ex 'set args insert < $gen_msg_filename' \ -x index-file-$code.gdb notmuch" - test_begin_subtest "success exit with --keep when add_message returns $code" + test_begin_subtest "success exit with --keep when index_file returns $code" test_expect_code 0 \ "${TEST_GDB} --batch-silent --return-child-result \ -ex 'set args insert --keep < $gen_msg_filename' \ @@ -219,13 +233,13 @@ for code in FILE_NOT_EMAIL READ_ONLY_DATABASE UPGRADE_REQUIRED PATH_ERROR; do done for code in OUT_OF_MEMORY XAPIAN_EXCEPTION ; do - test_begin_subtest "EX_TEMPFAIL when add_message returns $code" + test_begin_subtest "EX_TEMPFAIL when index_file returns $code" test_expect_code 75 \ "${TEST_GDB} --batch-silent --return-child-result \ -ex 'set args insert < $gen_msg_filename' \ -x index-file-$code.gdb notmuch" - test_begin_subtest "success exit with --keep when add_message returns $code" + test_begin_subtest "success exit with --keep when index_file returns $code" test_expect_code 0 \ "${TEST_GDB} --batch-silent --return-child-result \ -ex 'set args insert --keep < $gen_msg_filename' \ diff --git a/test/T080-search.sh b/test/T080-search.sh index d2d71ca9..70f28549 100755 --- a/test/T080-search.sh +++ b/test/T080-search.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash test_description='"notmuch search" in several variations' -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 add_email_corpus @@ -111,7 +111,7 @@ thread:XXX 2009-11-18 [3/3] Adrian Perez de Castro, Keith Packard, Carl Worth; thread:XXX 2009-11-18 [3/3] Israel Herraiz, Keith Packard, Carl Worth; [notmuch] New to the list (inbox unread) thread:XXX 2009-11-18 [3/3] Jan Janak, Carl Worth; [notmuch] What a great idea! (inbox unread) thread:XXX 2009-11-18 [2/2] Jan Janak, Carl Worth; [notmuch] [PATCH] Older versions of install do not support -C. (inbox unread) -thread:XXX 2009-11-18 [3/3] Aron Griffis, Keith Packard, Carl Worth; [notmuch] archive (inbox unread) +thread:XXX 2009-11-18 [3/3(4)] Aron Griffis, Keith Packard, Carl Worth; [notmuch] archive (inbox unread) thread:XXX 2009-11-18 [2/2] Keith Packard, Carl Worth; [notmuch] [PATCH] Make notmuch-show 'X' (and 'x') commands remove inbox (and unread) tags (inbox unread) thread:XXX 2009-11-18 [7/7] Lars Kellogg-Stedman, Mikhail Gusarov, Keith Packard, Carl Worth; [notmuch] Working with Maildir storage? (inbox signed unread) thread:XXX 2009-11-18 [5/5] Mikhail Gusarov, Carl Worth, Keith Packard; [notmuch] [PATCH 1/2] Close message file after parsing message headers (inbox unread) diff --git a/test/T090-search-output.sh b/test/T090-search-output.sh index dccefcb7..bf28d220 100755 --- a/test/T090-search-output.sh +++ b/test/T090-search-output.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash test_description='various settings for "notmuch search --output="' -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 add_email_corpus diff --git a/test/T095-address.sh b/test/T095-address.sh index 5931b147..817be538 100755 --- a/test/T095-address.sh +++ b/test/T095-address.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash test_description='"notmuch address" in several variants' -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 add_email_corpus @@ -119,6 +119,42 @@ cat <<EOF >EXPECTED EOF test_expect_equal_file EXPECTED OUTPUT +test_begin_subtest "--output=recipients --output=address" +notmuch address --output=recipients --output=address '*' >OUTPUT +cat <<EOF >EXPECTED +allan@archlinux.org +aur-general@archlinux.org +olivier.berger@it-sudparis.eu +notmuch@notmuchmail.org +notmuch@notmuchmail.org +keithp@keithp.com +dottedmag@dottedmag.net +EOF +test_expect_equal_file EXPECTED OUTPUT + +test_begin_subtest "--output=sender --output=address --output=count" +notmuch address --output=sender --output=address --output=count '*' | sort -n >OUTPUT +cat <<EOF >EXPECTED +1 agriffis@n01se.net +1 aperez@igalia.com +1 boulogne.f@gmail.com +1 chris@chris-wilson.co.uk +1 ingmar@exherbo.org +1 isra@herraiz.org +1 olivier.berger@it-sudparis.eu +1 rollandsantimano@yahoo.com +2 alex.boterolowry@gmail.com +2 gzjjgod@gmail.com +3 stewart@flamingspork.com +4 alex.boterolowry@gmail.com +4 jan@ryngle.com +5 dottedmag@dottedmag.net +5 lars@seas.harvard.edu +7 keithp@keithp.com +12 cworth@cworth.org +EOF +test_expect_equal_file EXPECTED OUTPUT + test_begin_subtest "--output=count --format=json" # Since the iteration order of GHashTable is not specified, we # preprocess and sort the results to keep the order stable here. diff --git a/test/T100-search-by-folder.sh b/test/T100-search-by-folder.sh index 2844ec61..a090f3d2 100755 --- a/test/T100-search-by-folder.sh +++ b/test/T100-search-by-folder.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash test_description='"notmuch search" by folder: and path: (with variations)' -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 add_message '[dir]=bad' '[subject]="To the bone"' add_message '[dir]=.' '[subject]="Top level"' @@ -15,7 +15,7 @@ add_message '[dir]=things/bad' '[subject]="Bites, stings, sad feelings"' test_begin_subtest "Single-world folder: specification (multiple results)" output=$(notmuch search folder:bad folder:bad/news folder:things/bad | notmuch_search_sanitize) test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; To the bone (inbox unread) -thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Bears (inbox unread) +thread:XXX 2001-01-05 [1/1(2)] Notmuch Test Suite; Bears (inbox unread) thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Bites, stings, sad feelings (inbox unread)" test_begin_subtest "Top level folder" @@ -24,7 +24,7 @@ test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; T test_begin_subtest "Two-word path to narrow results to one" output=$(notmuch search folder:bad/news | notmuch_search_sanitize) -test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Bears (inbox unread)" +test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1(2)] Notmuch Test Suite; Bears (inbox unread)" test_begin_subtest "Folder search with --output=files" output=$(notmuch search --output=files folder:bad/news | notmuch_search_files_sanitize) diff --git a/test/T110-search-position-overlap-bug.sh b/test/T110-search-position-overlap-bug.sh index 2a4238f9..f4d5ee14 100755 --- a/test/T110-search-position-overlap-bug.sh +++ b/test/T110-search-position-overlap-bug.sh @@ -18,7 +18,7 @@ # id:3wd4o8wa7fx.fsf@testarossa.amd.com test_description='that notmuch does not overlap term positions' -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 add_message '[to]="a@b.c, x@y.z"' diff --git a/test/T120-search-insufficient-from-quoting.sh b/test/T120-search-insufficient-from-quoting.sh index 4862d826..509fec8b 100755 --- a/test/T120-search-insufficient-from-quoting.sh +++ b/test/T120-search-insufficient-from-quoting.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash test_description='messages with unquoted . in name' -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 add_message \ '[from]="Some.Name for Someone <bugs@quoting.com>"' \ diff --git a/test/T130-search-limiting.sh b/test/T130-search-limiting.sh index c8986f4e..8a30e7ab 100755 --- a/test/T130-search-limiting.sh +++ b/test/T130-search-limiting.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash test_description='"notmuch search" --offset and --limit parameters' -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 add_email_corpus diff --git a/test/T140-excludes.sh b/test/T140-excludes.sh index f91d4d7f..0cf69975 100755 --- a/test/T140-excludes.sh +++ b/test/T140-excludes.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash test_description='"notmuch search, count and show" with excludes in several variations' -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 # Generates a thread consisting of a top level message and 'length' # replies. The subject of the top message 'subject: top message" diff --git a/test/T150-tagging.sh b/test/T150-tagging.sh index 0d0a3b87..6140c676 100755 --- a/test/T150-tagging.sh +++ b/test/T150-tagging.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash test_description='"notmuch tag"' -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 add_message '[subject]=One' add_message '[subject]=Two' diff --git a/test/T160-json.sh b/test/T160-json.sh index ac51895e..91b98e5d 100755 --- a/test/T160-json.sh +++ b/test/T160-json.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash test_description="--format=json output" -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 test_begin_subtest "Show message: json" add_message "[subject]=\"json-show-subject\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[bcc]=\"test_suite+bcc@notmuchmail.org\"" "[reply-to]=\"test_suite+replyto@notmuchmail.org\"" "[body]=\"json-show-message\"" @@ -41,13 +41,13 @@ id="json-show-inline-attachment-filename@notmuchmail.org" emacs_fcc_message \ "$subject" \ 'This is a test message with inline attachment with a filename' \ - "(mml-attach-file \"$TEST_DIRECTORY/README\" nil nil \"inline\") + "(mml-attach-file \"$NOTMUCH_SRCDIR/test/README\" nil nil \"inline\") (message-goto-eoh) (insert \"Message-ID: <$id>\n\")" output=$(notmuch show --format=json "id:$id") filename=$(notmuch search --output=files "id:$id") # Get length of README after base64-encoding, minus additional newline. -attachment_length=$(( $(base64 $TEST_DIRECTORY/README | wc -c) - 1 )) +attachment_length=$(( $(base64 $NOTMUCH_SRCDIR/test/README | wc -c) - 1 )) test_expect_equal_json "$output" "[[[{\"id\": \"$id\", \"match\": true, \"excluded\": false, \"filename\": [\"$filename\"], \"timestamp\": 946728000, \"date_relative\": \"2000-01-01\", \"tags\": [\"inbox\"], \"headers\": {\"Subject\": \"$subject\", \"From\": \"Notmuch Test Suite <test_suite@notmuchmail.org>\", \"To\": \"test_suite@notmuchmail.org\", \"Date\": \"Sat, 01 Jan 2000 12:00:00 +0000\"}, \"body\": [{\"id\": 1, \"content-type\": \"multipart/mixed\", \"content\": [{\"id\": 2, \"content-type\": \"text/plain\", \"content\": \"This is a test message with inline attachment with a filename\"}, {\"id\": 3, \"content-type\": \"application/octet-stream\", \"content-length\": $attachment_length, \"content-transfer-encoding\": \"base64\", \"content-disposition\": \"inline\", \"filename\": \"README\"}]}]}, []]]]" test_begin_subtest "Search message: json, utf-8" @@ -71,8 +71,8 @@ test_begin_subtest "Format version: too high" test_expect_code 21 "notmuch search --format-version=999 \\*" test_begin_subtest "Show message: multiple filenames" -add_message "[id]=message-id@example.com [filename]=copy1" -add_message "[id]=message-id@example.com [filename]=copy2" +add_message '[id]=message-id@example.com [filename]=copy1 [date]="Fri, 05 Jan 2001 15:43:52 +0000"' +add_message '[id]=message-id@example.com [filename]=copy2 [date]="Fri, 05 Jan 2001 15:43:52 +0000"' cat <<EOF > EXPECTED [ [ diff --git a/test/T170-sexp.sh b/test/T170-sexp.sh index 40e5e21d..c3dcf52a 100755 --- a/test/T170-sexp.sh +++ b/test/T170-sexp.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash test_description="--format=sexp output" -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 test_begin_subtest "Show message: sexp" add_message "[subject]=\"sexp-show-subject\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[bcc]=\"test_suite+bcc@notmuchmail.org\"" "[reply-to]=\"test_suite+replyto@notmuchmail.org\"" "[body]=\"sexp-show-message\"" @@ -26,25 +26,24 @@ add_message "[subject]=\"sexp-show-utf8-body-sübjéct\"" "[date]=\"Sat, 01 Jan output=$(notmuch show --format=sexp "jsön-show-méssage") test_expect_equal "$output" "((((:id \"${gen_msg_id}\" :match t :excluded nil :filename (\"${gen_msg_filename}\") :timestamp 946728000 :date_relative \"2000-01-01\" :tags (\"inbox\" \"unread\") :headers (:Subject \"sexp-show-utf8-body-sübjéct\" :From \"Notmuch Test Suite <test_suite@notmuchmail.org>\" :To \"Notmuch Test Suite <test_suite@notmuchmail.org>\" :Date \"Sat, 01 Jan 2000 12:00:00 +0000\") :body ((:id 1 :content-type \"text/plain\" :content \"jsön-show-méssage\n\"))) ())))" +test_begin_subtest "Search message: sexp, utf-8" +add_message "[subject]=\"sexp-search-utf8-body-sübjéct\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[body]=\"jsön-search-méssage\"" +output=$(notmuch search --format=sexp "jsön-search-méssage" | notmuch_search_sanitize) +test_expect_equal "$output" "((:thread \"0000000000000004\" :timestamp 946728000 :date_relative \"2000-01-01\" :matched 1 :total 1 :authors \"Notmuch Test Suite\" :subject \"sexp-search-utf8-body-sübjéct\" :query (\"id:$gen_msg_id\" nil) :tags (\"inbox\" \"unread\")))" + test_begin_subtest "Show message: sexp, inline attachment filename" subject='sexp-show-inline-attachment-filename' id="sexp-show-inline-attachment-filename@notmuchmail.org" emacs_fcc_message \ "$subject" \ 'This is a test message with inline attachment with a filename' \ - "(mml-attach-file \"$TEST_DIRECTORY/README\" nil nil \"inline\") + "(mml-attach-file \"$NOTMUCH_SRCDIR/test/README\" nil nil \"inline\") (message-goto-eoh) (insert \"Message-ID: <$id>\n\")" output=$(notmuch show --format=sexp "id:$id") filename=$(notmuch search --output=files "id:$id") # Get length of README after base64-encoding, minus additional newline. -attachment_length=$(( $(base64 $TEST_DIRECTORY/README | wc -c) - 1 )) +attachment_length=$(( $(base64 $NOTMUCH_SRCDIR/test/README | wc -c) - 1 )) test_expect_equal "$output" "((((:id \"$id\" :match t :excluded nil :filename (\"$filename\") :timestamp 946728000 :date_relative \"2000-01-01\" :tags (\"inbox\") :headers (:Subject \"sexp-show-inline-attachment-filename\" :From \"Notmuch Test Suite <test_suite@notmuchmail.org>\" :To \"test_suite@notmuchmail.org\" :Date \"Sat, 01 Jan 2000 12:00:00 +0000\") :body ((:id 1 :content-type \"multipart/mixed\" :content ((:id 2 :content-type \"text/plain\" :content \"This is a test message with inline attachment with a filename\") (:id 3 :content-type \"application/octet-stream\" :content-disposition \"inline\" :filename \"README\" :content-transfer-encoding \"base64\" :content-length $attachment_length))))) ())))" -test_begin_subtest "Search message: sexp, utf-8" -add_message "[subject]=\"sexp-search-utf8-body-sübjéct\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[body]=\"jsön-search-méssage\"" -output=$(notmuch search --format=sexp "jsön-search-méssage" | notmuch_search_sanitize) -test_expect_equal "$output" "((:thread \"0000000000000005\" :timestamp 946728000 :date_relative \"2000-01-01\" :matched 1 :total 1 :authors \"Notmuch Test Suite\" :subject \"sexp-search-utf8-body-sübjéct\" :query (\"id:$gen_msg_id\" nil) :tags (\"inbox\" \"unread\")))" - - test_done diff --git a/test/T180-text.sh b/test/T180-text.sh index 3a265dbd..ad2cb1f3 100755 --- a/test/T180-text.sh +++ b/test/T180-text.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash test_description="--format=text output" -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 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\"" diff --git a/test/T190-multipart.sh b/test/T190-multipart.sh index 94bb0570..f73535b7 100755 --- a/test/T190-multipart.sh +++ b/test/T190-multipart.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash test_description="output of multipart message" -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 cat <<EOF > embedded_message_body Content-Type: multipart/alternative; boundary="==-=-==" diff --git a/test/T200-thread-naming.sh b/test/T200-thread-naming.sh index 2167ba8e..594d301f 100755 --- a/test/T200-thread-naming.sh +++ b/test/T200-thread-naming.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash test_description="naming of threads with changing subject" -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 test_begin_subtest "Initial thread name (oldest-first search)" add_message '[subject]="thread-naming: Initial thread subject"' \ diff --git a/test/T205-author-naming.sh b/test/T205-author-naming.sh index 69d8dc50..68b85ced 100755 --- a/test/T205-author-naming.sh +++ b/test/T205-author-naming.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash test_description="naming of authors with unusual addresses" -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 test_begin_subtest "Add author with empty quoted real name" add_message '[subject]="author-naming: Initial thread subject"' \ diff --git a/test/T210-raw.sh b/test/T210-raw.sh index 832a4ad3..99fdef72 100755 --- a/test/T210-raw.sh +++ b/test/T210-raw.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash test_description='notmuch show --format=raw' -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 add_message add_message diff --git a/test/T220-reply.sh b/test/T220-reply.sh index 4fb67ffb..ebe710f9 100755 --- a/test/T220-reply.sh +++ b/test/T220-reply.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash test_description="\"notmuch reply\" in several variations" -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 test_begin_subtest "Basic reply" add_message '[from]="Sender <sender@example.com>"' \ diff --git a/test/T230-reply-to-sender.sh b/test/T230-reply-to-sender.sh index 608334dc..134a1063 100755 --- a/test/T230-reply-to-sender.sh +++ b/test/T230-reply-to-sender.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash test_description="\"notmuch reply --reply-to=sender\" in several variations" -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 test_begin_subtest "Basic reply-to-sender" add_message '[from]="Sender <sender@example.com>"' \ diff --git a/test/T240-dump-restore.sh b/test/T240-dump-restore.sh index 75fb0b40..0870ff92 100755 --- a/test/T240-dump-restore.sh +++ b/test/T240-dump-restore.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash test_description="\"notmuch dump\" and \"notmuch restore\"" -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 NOTMUCH_NEW > /dev/null test_begin_subtest "dump header" diff --git a/test/T250-uuencode.sh b/test/T250-uuencode.sh index 6f45d395..251c0b40 100755 --- a/test/T250-uuencode.sh +++ b/test/T250-uuencode.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash test_description="handling of uuencoded data" -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 add_message [subject]=uuencodetest '[date]="Sat, 01 Jan 2000 12:00:00 -0000"' \ '[body]="This message is used to ensure that notmuch correctly handles a diff --git a/test/T260-thread-order.sh b/test/T260-thread-order.sh index 89f4d1be..fea61275 100755 --- a/test/T260-thread-order.sh +++ b/test/T260-thread-order.sh @@ -1,10 +1,10 @@ #!/usr/bin/env bash test_description="threading when messages received out of order" -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 # Generate all single-root four message thread structures. We'll use # this for multiple tests below. -THREADS=$($NOTMUCH_PYTHON ${TEST_DIRECTORY}/gen-threads.py 4) +THREADS=$($NOTMUCH_PYTHON ${NOTMUCH_SRCDIR}/test/gen-threads.py 4) nthreads=$(wc -l <<< "$THREADS") test_begin_subtest "Messages with one parent get linked in all delivery orders" diff --git a/test/T270-author-order.sh b/test/T270-author-order.sh index 9124ece6..c28ecb02 100755 --- a/test/T270-author-order.sh +++ b/test/T270-author-order.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash test_description="author reordering;" -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 test_begin_subtest "Adding parent message" generate_message [body]=findme [id]=new-parent-id [subject]=author-reorder-threadtest '[from]="User <user@example.com>"' '[date]="Sat, 01 Jan 2000 12:00:00 -0000"' diff --git a/test/T280-from-guessing.sh b/test/T280-from-guessing.sh index 7c562fb9..b8718232 100755 --- a/test/T280-from-guessing.sh +++ b/test/T280-from-guessing.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash test_description="From line heuristics (with multiple configured addresses)" -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 test_begin_subtest "Magic from guessing (nothing to go on)" add_message '[from]="Sender <sender@example.com>"' \ diff --git a/test/T290-long-id.sh b/test/T290-long-id.sh index 1fb7c037..5e3879f5 100755 --- a/test/T290-long-id.sh +++ b/test/T290-long-id.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash test_description="messages with ridiculously-long message IDs" -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 test_begin_subtest "Referencing long ID before adding" generate_message '[subject]="Reference of ridiculously-long message ID"' \ diff --git a/test/T300-encoding.sh b/test/T300-encoding.sh index 8d201c7e..2c656a1e 100755 --- a/test/T300-encoding.sh +++ b/test/T300-encoding.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash test_description="encoding issues" -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 test_begin_subtest "Message with text of unknown charset" add_message '[content-type]="text/plain; charset=unknown-8bit"' \ diff --git a/test/T310-emacs.sh b/test/T310-emacs.sh index fde11790..ba08167f 100755 --- a/test/T310-emacs.sh +++ b/test/T310-emacs.sh @@ -1,15 +1,15 @@ #!/usr/bin/env bash test_description="emacs interface" -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 -EXPECTED=$TEST_DIRECTORY/emacs.expected-output +EXPECTED=$NOTMUCH_SRCDIR/test/emacs.expected-output add_email_corpus # syntax errors in test-lib.el cause mysterious failures test_begin_subtest "Syntax of emacs test library" -test_expect_success "${TEST_EMACS} -Q --batch --load $TEST_DIRECTORY/test-lib.el" +test_expect_success "${TEST_EMACS} -Q --batch --load $NOTMUCH_SRCDIR/test/test-lib.el" test_begin_subtest "Basic notmuch-hello view in emacs" test_emacs '(notmuch-hello) @@ -401,6 +401,28 @@ Notmuch Test Suite <test_suite@notmuchmail.org> writes: EOF test_expect_equal_file EXPECTED OUTPUT +test_begin_subtest "Reply within emacs to a message with TAB in subject" +test_emacs '(let ((message-hidden-headers ''())) + (notmuch-search "id:1258471718-6781-1-git-send-email-dottedmag@dottedmag.net") + (notmuch-test-wait) + (notmuch-search-show-thread) + (notmuch-test-wait) + (notmuch-show-reply-sender) + (test-output))' +sed -i -e 's/^In-Reply-To: <.*>$/In-Reply-To: <XXX>/' OUTPUT +sed -i -e 's/^References: <.*>$/References: <XXX>/' OUTPUT +sed -i -e '/^--text follows this line--$/q' OUTPUT +cat <<EOF >EXPECTED +From: Notmuch Test Suite <test_suite@notmuchmail.org> +To: Mikhail Gusarov <dottedmag@dottedmag.net> +Subject: Re: [notmuch] [PATCH 1/2] Close message file after parsing message headers +In-Reply-To: <XXX> +Fcc: ${MAIL_DIR}/sent +References: <XXX> +--text follows this line-- +EOF +test_expect_equal_file EXPECTED OUTPUT + test_begin_subtest "Reply from alternate address within emacs" add_message '[from]="Sender <sender@example.com>"' \ [to]=test_suite_other@notmuchmail.org diff --git a/test/T320-emacs-large-search-buffer.sh b/test/T320-emacs-large-search-buffer.sh index e9d5e358..f61e8a97 100755 --- a/test/T320-emacs-large-search-buffer.sh +++ b/test/T320-emacs-large-search-buffer.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash test_description="Emacs with large search results buffer" -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 x=xxxxxxxxxx # 10 x=$x$x$x$x$x$x$x$x$x$x # 100 diff --git a/test/T330-emacs-subject-to-filename.sh b/test/T330-emacs-subject-to-filename.sh index 517fa839..eaf7c980 100755 --- a/test/T330-emacs-subject-to-filename.sh +++ b/test/T330-emacs-subject-to-filename.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash test_description="emacs: mail subject to filename" -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 # emacs server can't be started in a child process with $(test_emacs ...) test_emacs '(ignore)' > /dev/null diff --git a/test/T340-maildir-sync.sh b/test/T340-maildir-sync.sh index 6d956635..7fece5f2 100755 --- a/test/T340-maildir-sync.sh +++ b/test/T340-maildir-sync.sh @@ -2,7 +2,7 @@ test_description="maildir synchronization" -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 # Create the expected maildir structure mkdir $MAIL_DIR/cur @@ -28,6 +28,14 @@ add_message [subject]='"Adding message with S"' [filename]='adding-with-s-flag:2 output=$(notmuch search subject:"Adding message with S" | notmuch_search_sanitize) test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Adding message with S (inbox)" +test_begin_subtest "Adding message with 'S' w/o 'unread' in new.tags prevents 'unread' tag" +OLDCONFIG=$(notmuch config get new.tags) +notmuch config set new.tags "inbox" +add_message [subject]='"Adding message with S 2"' [filename]='adding-with-s-flag2:2,S' [dir]=cur +notmuch config set new.tags $OLDCONFIG +output=$(notmuch search subject:Adding-message-with-S-2 | notmuch_search_sanitize) +test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Adding message with S 2 (inbox)" + test_begin_subtest "Adding 'replied' tag adds 'R' flag to filename" add_message [subject]='"Adding replied tag"' [filename]='adding-replied-tag:2,S' [dir]=cur notmuch tag +replied subject:"Adding replied tag" @@ -49,7 +57,7 @@ test_expect_equal_json "$output" '[[[{"id": "XXXXX", "Date": "GENERATED_DATE"}, "body": [{"id": 1, "content-type": "text/plain", -"content": "This is just a test message (#3)\n"}]}, +"content": "This is just a test message (#4)\n"}]}, []]]]' test_begin_subtest "notmuch reply works with renamed file (without notmuch new)" @@ -153,14 +161,14 @@ cp "$MAIL_DIR/cur/duplicated-message:2," "$MAIL_DIR/cur/duplicated-message-copy: NOTMUCH_NEW > output notmuch search subject:"Duplicated message" | notmuch_search_sanitize >> output test_expect_equal "$(< output)" "No new mail. -thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Duplicated message (inbox replied)" +thread:XXX 2001-01-05 [1/1(2)] Notmuch Test Suite; Duplicated message (inbox replied)" test_begin_subtest "Adding duplicate message without flags does not remove tags" cp "$MAIL_DIR/cur/duplicated-message-copy:2,RS" "$MAIL_DIR/cur/duplicated-message-another-copy:2," NOTMUCH_NEW > output notmuch search subject:"Duplicated message" | notmuch_search_sanitize >> output test_expect_equal "$(< output)" "No new mail. -thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Duplicated message (inbox replied)" +thread:XXX 2001-01-05 [1/1(3)] Notmuch Test Suite; Duplicated message (inbox replied)" test_begin_subtest "Tag changes modify flags of multiple files" notmuch tag -replied subject:"Duplicated message" @@ -181,11 +189,21 @@ test_expect_equal "$(cd $MAIL_DIR/cur/; ls non-compliant*)" "non-compliant-maild test_begin_subtest "Files in new/ get default synchronized tags" OLDCONFIG=$(notmuch config get new.tags) -notmuch config set new.tags test +notmuch config set new.tags "test;unread" 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)" +for tag in draft flagged passed replied; do + test_begin_subtest "$tag is valid in new.tags" + OLDCONFIG=$(notmuch config get new.tags) + notmuch config set new.tags "$tag;unread" + add_message [subject]="\"$tag sync in new\"" [dir]=new + notmuch config set new.tags $OLDCONFIG + notmuch search "subject:\"$tag sync in new\"" | notmuch_search_sanitize > output + test_expect_equal "$(< output)" \ + "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; $tag sync in new ($tag unread)" +done test_done diff --git a/test/T350-crypto.sh b/test/T350-crypto.sh index 7dab39a2..a776ec35 100755 --- a/test/T350-crypto.sh +++ b/test/T350-crypto.sh @@ -5,24 +5,7 @@ # - verification of signatures from expired/revoked keys test_description='PGP/MIME signature verification and decryption' -. ./test-lib.sh || exit 1 - -add_gnupg_home () -{ - local output - [ -d ${GNUPGHOME} ] && return - _gnupg_exit () { gpgconf --kill all 2>/dev/null || true; } - at_exit_function _gnupg_exit - mkdir -m 0700 "$GNUPGHOME" - gpg --no-tty --import <$TEST_DIRECTORY/gnupg-secret-key.asc >"$GNUPGHOME"/import.log 2>&1 - test_debug "cat $GNUPGHOME/import.log" - if (gpg --quick-random --version >/dev/null 2>&1) ; then - echo quick-random >> "$GNUPGHOME"/gpg.conf - elif (gpg --debug-quick-random --version >/dev/null 2>&1) ; then - echo debug-quick-random >> "$GNUPGHOME"/gpg.conf - fi - echo no-emit-version >> "$GNUPGHOME"/gpg.conf -} +. $(dirname "$0")/test-lib.sh || exit 1 ################################################## @@ -37,6 +20,10 @@ test_expect_success \ "This is a test signed message." \ "(mml-secure-message-sign)"' +test_begin_subtest "signed part content-type indexing" +output=$(notmuch search mimetype:multipart/signed and mimetype:application/pgp-signature | notmuch_search_sanitize) +test_expect_equal "$output" "thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; test signed message 001 (inbox signed)" + test_begin_subtest "signature verification" output=$(notmuch show --format=json --verify subject:"test signed message 001" \ | notmuch_json_show_sanitize \ @@ -231,8 +218,12 @@ test_expect_success \ "This is a test encrypted message.\n" \ "(mml-attach-file \"TESTATTACHMENT\") (mml-secure-message-encrypt)"' +test_begin_subtest "encrypted part content-type indexing" +output=$(notmuch search mimetype:multipart/encrypted and mimetype:application/pgp-encrypted and mimetype:application/octet-stream | notmuch_search_sanitize) +test_expect_equal "$output" "thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; test encrypted message 001 (encrypted inbox)" + test_begin_subtest "decryption, --format=text" -output=$(notmuch show --format=text --decrypt subject:"test encrypted message 001" \ +output=$(notmuch show --format=text --decrypt=true subject:"test encrypted message 001" \ | notmuch_show_sanitize_all \ | sed -e 's|"created": [1234567890]*|"created": 946728000|') expected='message{ id:XXXXX depth:0 match:1 excluded:0 filename:XXXXX @@ -264,7 +255,7 @@ test_expect_equal \ "$expected" test_begin_subtest "decryption, --format=json" -output=$(notmuch show --format=json --decrypt subject:"test encrypted message 001" \ +output=$(notmuch show --format=json --decrypt=true subject:"test encrypted message 001" \ | notmuch_json_show_sanitize \ | sed -e 's|"created": [1234567890]*|"created": 946728000|') expected='[[[{"id": "XXXXX", @@ -302,7 +293,7 @@ test_expect_equal_json \ "$expected" test_begin_subtest "decryption, --format=json, --part=4" -output=$(notmuch show --format=json --part=4 --decrypt subject:"test encrypted message 001" \ +output=$(notmuch show --format=json --part=4 --decrypt=true subject:"test encrypted message 001" \ | notmuch_json_show_sanitize \ | sed -e 's|"created": [1234567890]*|"created": 946728000|') expected='{"id": 4, @@ -316,13 +307,13 @@ test_begin_subtest "decrypt attachment (--part=5 --format=raw)" notmuch show \ --format=raw \ --part=5 \ - --decrypt \ + --decrypt=true \ subject:"test encrypted message 001" >OUTPUT test_expect_equal_file TESTATTACHMENT OUTPUT test_begin_subtest "decryption failure with missing key" mv "${GNUPGHOME}"{,.bak} -output=$(notmuch show --format=json --decrypt subject:"test encrypted message 001" \ +output=$(notmuch show --format=json --decrypt=true subject:"test encrypted message 001" \ | notmuch_json_show_sanitize \ | sed -e 's|"created": [1234567890]*|"created": 946728000|') expected='[[[{"id": "XXXXX", @@ -360,7 +351,7 @@ test_expect_success \ test_begin_subtest "decryption + signature verification" test_subtest_broken_gmime_2 -output=$(notmuch show --format=json --decrypt subject:"test encrypted message 002" \ +output=$(notmuch show --format=json --decrypt=true subject:"test encrypted message 002" \ | notmuch_json_show_sanitize \ | sed -e 's|"created": [1234567890]*|"created": 946728000|') expected='[[[{"id": "XXXXX", @@ -393,8 +384,8 @@ test_expect_equal_json \ "$expected" test_begin_subtest "reply to encrypted message" -output=$(notmuch reply --decrypt subject:"test encrypted message 002" \ - | grep -v -e '^In-Reply-To:' -e '^References:') +output=$(notmuch reply --decrypt=true subject:"test encrypted message 002" \ + | notmuch_drop_mail_headers In-Reply-To References) expected='From: Notmuch Test Suite <test_suite@notmuchmail.org> Subject: Re: test encrypted message 002 diff --git a/test/T355-smime.sh b/test/T355-smime.sh index 03d24581..be45e3b1 100755 --- a/test/T355-smime.sh +++ b/test/T355-smime.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash test_description='S/MIME signature verification and decryption' -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 add_gpgsm_home () { @@ -10,7 +10,7 @@ add_gpgsm_home () _gnupg_exit () { gpgconf --kill all 2>/dev/null || true; } at_exit_function _gnupg_exit mkdir -m 0700 "$GNUPGHOME" - gpgsm --no-tty --no-common-certs-import --disable-dirmngr --import < $TEST_DIRECTORY/smime/test.crt >"$GNUPGHOME"/import.log 2>&1 + gpgsm --no-tty --no-common-certs-import --disable-dirmngr --import < $NOTMUCH_SRCDIR/test/smime/test.crt >"$GNUPGHOME"/import.log 2>&1 fpr=$(gpgsm --list-key test_suite@notmuchmail.org | sed -n 's/.*fingerprint: //p') echo "$fpr S relax" >> $GNUPGHOME/trustlist.txt test_debug "cat $GNUPGHOME/import.log" @@ -19,7 +19,7 @@ add_gpgsm_home () test_require_external_prereq openssl test_require_external_prereq gpgsm -cp $TEST_DIRECTORY/smime/key+cert.pem test_suite.pem +cp $NOTMUCH_SRCDIR/test/smime/key+cert.pem test_suite.pem FINGERPRINT=$(openssl x509 -fingerprint -in test_suite.pem -noout | sed -e 's/^.*=//' -e s/://g) @@ -41,13 +41,19 @@ test_expect_success \ test_begin_subtest "Signature verification (openssl)" notmuch show --format=raw subject:"test signed message 001" |\ - openssl smime -verify -CAfile $TEST_DIRECTORY/smime/test.crt 2>OUTPUT + openssl smime -verify -CAfile $NOTMUCH_SRCDIR/test/smime/test.crt 2>OUTPUT cat <<EOF > EXPECTED Verification successful EOF test_expect_equal_file EXPECTED OUTPUT test_begin_subtest "signature verification (notmuch CLI)" +if [ "${NOTMUCH_GMIME_MAJOR}" -lt 3 ]; then + # gmime 2 can't report User IDs properly for S/MIME + USERID='' +else + USERID='"userid": "CN=Notmuch Test Suite",' +fi output=$(notmuch show --format=json --verify subject:"test signed message 001" \ | notmuch_json_show_sanitize \ | sed -e 's|"created": [-1234567890]*|"created": 946728000|' \ @@ -65,7 +71,7 @@ expected='[[[{"id": "XXXXX", "Date": "Sat, 01 Jan 2000 12:00:00 +0000"}, "body": [{"id": 1, "sigstatus": [{"fingerprint": "'$FINGERPRINT'", - "status": "good", + "status": "good",'$USERID' "expires": 424242424, "created": 946728000}], "content-type": "multipart/signed", @@ -86,7 +92,7 @@ test_expect_equal_json \ test_begin_subtest "Decryption and signature verification (openssl)" notmuch show --format=raw subject:"test encrypted message 001" |\ openssl smime -decrypt -recip test_suite.pem |\ - openssl smime -verify -CAfile $TEST_DIRECTORY/smime/test.crt 2>OUTPUT + openssl smime -verify -CAfile $NOTMUCH_SRCDIR/test/smime/test.crt 2>OUTPUT cat <<EOF > EXPECTED Verification successful EOF diff --git a/test/T357-index-decryption.sh b/test/T357-index-decryption.sh new file mode 100755 index 00000000..2b8e05b8 --- /dev/null +++ b/test/T357-index-decryption.sh @@ -0,0 +1,303 @@ +#!/usr/bin/env bash + +# TODO: test index.decryption=failed + +test_description='indexing decrypted mail' +. $(dirname "$0")/test-lib.sh || exit 1 + +################################################## + +add_gnupg_home +# get key fingerprint +FINGERPRINT=$(gpg --no-tty --list-secret-keys --with-colons --fingerprint | grep '^fpr:' | cut -d: -f10) + +# create a test encrypted message +test_begin_subtest 'emacs delivery of encrypted message' +test_expect_success \ +'emacs_fcc_message \ + "test encrypted message for cleartext index 001" \ + "This is a test encrypted message with a wumpus.\n" \ + "(mml-secure-message-encrypt)"' + +test_begin_subtest "search for unindexed cleartext" +output=$(notmuch search wumpus) +expected='' +test_expect_equal \ + "$output" \ + "$expected" + +# create a test encrypted message that is indexed in the clear +test_begin_subtest 'emacs delivery of encrypted message' +test_expect_success \ +'emacs_fcc_message --decrypt=true \ + "test encrypted message for cleartext index 002" \ + "This is a test encrypted message with a wumpus.\n" \ + "(mml-secure-message-encrypt)"' + +test_begin_subtest "emacs delivery of encrypted message, indexed cleartext" +output=$(notmuch search wumpus) +expected='thread:0000000000000002 2000-01-01 [1/1] Notmuch Test Suite; test encrypted message for cleartext index 002 (encrypted inbox)' +test_expect_equal \ + "$output" \ + "$expected" + +# and the same search, but by property ($expected is untouched): +test_begin_subtest "emacs search by property for one message" +output=$(notmuch search property:index.decryption=success) +test_expect_equal \ + "$output" \ + "$expected" + +test_begin_subtest "show the message body of the encrypted message" +notmuch dump wumpus +output=$(notmuch show wumpus | awk '/^\014part}/{ f=0 }; { if (f) { print $0 } } /^\014part{ ID: 3/{ f=1 }') +expected='This is a test encrypted message with a wumpus.' +if [ $NOTMUCH_HAVE_GMIME_SESSION_KEYS -eq 0 ]; then + test_subtest_known_broken +fi +test_expect_equal \ + "$output" \ + "$expected" + + +test_begin_subtest "message should go away after deletion" +# cache the message in an env var and remove it: +fname=$(notmuch search --output=files wumpus) +contents="$(notmuch show --format=raw wumpus)" +rm -f "$fname" +notmuch new +output=$(notmuch search wumpus) +expected='' +test_expect_equal \ + "$output" \ + "$expected" + +# try reinserting it without decryption, should stay the same: +test_begin_subtest "message cleartext not present after insert" +notmuch insert --folder=sent <<<"$contents" +output=$(notmuch search wumpus) +test_expect_equal \ + "$output" \ + "$expected" + +# try reinserting it with decryption, should appear again, but now we +# have two copies of the message: +test_begin_subtest "message cleartext is present after reinserting with --decrypt=true" +notmuch insert --folder=sent --decrypt=true <<<"$contents" +output=$(notmuch search wumpus) +expected='thread:0000000000000003 2000-01-01 [1/1(2)] Notmuch Test Suite; test encrypted message for cleartext index 002 (encrypted inbox unread)' +test_expect_equal \ + "$output" \ + "$expected" + +# remove all copies +test_begin_subtest "delete all copies of the message" +mid="$(notmuch search --output=messages wumpus)" +rm -f $(notmuch search --output=files wumpus) +notmuch new +output=$(notmuch search "id:$mid") +expected='' +test_expect_equal \ + "$output" \ + "$expected" + +# try inserting it with decryption, should appear as a single copy +# (note: i think thread id skips 4 because of duplicate message-id +# insertion, above) +test_begin_subtest "message cleartext is present with insert --decrypt=true" +notmuch insert --folder=sent --decrypt=true <<<"$contents" +output=$(notmuch search wumpus) +expected='thread:0000000000000005 2000-01-01 [1/1] Notmuch Test Suite; test encrypted message for cleartext index 002 (encrypted inbox unread)' +test_expect_equal \ + "$output" \ + "$expected" + + +# add a tag to all messages to ensure that it stays after reindexing +test_begin_subtest 'tagging all messages' +test_expect_success 'notmuch tag +blarney "encrypted message"' +test_begin_subtest "verify that tags have not changed" +output=$(notmuch search tag:blarney) +expected='thread:0000000000000001 2000-01-01 [1/1] Notmuch Test Suite; test encrypted message for cleartext index 001 (blarney encrypted inbox) +thread:0000000000000005 2000-01-01 [1/1] Notmuch Test Suite; test encrypted message for cleartext index 002 (blarney encrypted inbox unread)' +test_expect_equal \ + "$output" \ + "$expected" + +# see if first message shows up after reindexing with --decrypt=true (same $expected, untouched): +test_begin_subtest 'reindex old messages' +test_expect_success 'notmuch reindex --decrypt=true tag:encrypted and not property:index.decryption=success' +test_begin_subtest "reindexed encrypted message, including cleartext" +output=$(notmuch search wumpus) +test_expect_equal \ + "$output" \ + "$expected" + +# and the same search, but by property ($expected is untouched): +test_begin_subtest "emacs search by property for both messages" +output=$(notmuch search property:index.decryption=success) +test_expect_equal \ + "$output" \ + "$expected" + +# try a simple reindex +test_begin_subtest 'reindex in auto mode' +test_expect_success 'notmuch reindex tag:encrypted and property:index.decryption=success' +test_begin_subtest "reindexed encrypted messages, should not have changed" +output=$(notmuch search wumpus) +if [ $NOTMUCH_HAVE_GMIME_SESSION_KEYS -eq 0 ]; then + test_subtest_known_broken +fi +test_expect_equal \ + "$output" \ + "$expected" + +# try to remove cleartext indexing +test_begin_subtest 'reindex without cleartext' +test_expect_success 'notmuch reindex --decrypt=false tag:encrypted and property:index.decryption=success' +test_begin_subtest "reindexed encrypted messages, without cleartext" +output=$(notmuch search wumpus) +expected='' +test_expect_equal \ + "$output" \ + "$expected" + +# ensure no session keys are present: +test_begin_subtest 'reindex using only session keys' +test_expect_success 'notmuch reindex tag:encrypted and property:index.decryption=success' +test_begin_subtest "reindexed encrypted messages, decrypting only with session keys" +output=$(notmuch search wumpus) +expected='' +test_expect_equal \ + "$output" \ + "$expected" + +# and the same search, but by property ($expected is untouched): +test_begin_subtest "emacs search by property with both messages unindexed" +output=$(notmuch search property:index.decryption=success) +test_expect_equal \ + "$output" \ + "$expected" + +# ensure that the tags remain even when we are dropping the cleartext. +test_begin_subtest "verify that tags remain without cleartext" +output=$(notmuch search tag:blarney) +expected='thread:0000000000000001 2000-01-01 [1/1] Notmuch Test Suite; test encrypted message for cleartext index 001 (blarney encrypted inbox) +thread:0000000000000005 2000-01-01 [1/1] Notmuch Test Suite; test encrypted message for cleartext index 002 (blarney encrypted inbox unread)' +test_expect_equal \ + "$output" \ + "$expected" + +test_begin_subtest "index cleartext without keeping session keys" +test_expect_success "notmuch reindex --decrypt=nostash tag:blarney" + +test_begin_subtest "Ensure that the indexed terms are present" +output=$(notmuch search wumpus) +test_expect_equal \ + "$output" \ + "$expected" + +test_begin_subtest "show one of the messages with --decrypt=true" +output=$(notmuch show --decrypt=true thread:0000000000000001 | awk '/^\014part}/{ f=0 }; { if (f) { print $0 } } /^\014part{ ID: 3/{ f=1 }') +expected='This is a test encrypted message with a wumpus.' +test_expect_equal \ + "$output" \ + "$expected" + +test_begin_subtest "Ensure that we cannot show the message with --decrypt=auto" +output=$(notmuch show thread:0000000000000001 | awk '/^\014part}/{ f=0 }; { if (f) { print $0 } } /^\014part{ ID: 3/{ f=1 }') +expected='Non-text part: application/octet-stream' +test_expect_equal \ + "$output" \ + "$expected" + +add_email_corpus crypto + +test_begin_subtest "indexing message fails when secret key not available" +notmuch reindex --decrypt=true id:simple-encrypted@crypto.notmuchmail.org +output=$(notmuch dump ) +expected='#notmuch-dump batch-tag:3 config,properties,tags ++encrypted +inbox +unread -- id:simple-encrypted@crypto.notmuchmail.org +#= simple-encrypted@crypto.notmuchmail.org index.decryption=failure' +test_expect_equal \ + "$output" \ + "$expected" + +test_begin_subtest "cannot find cleartext index" +output=$(notmuch search sekrit) +expected='' +test_expect_equal \ + "$output" \ + "$expected" + +test_begin_subtest "cleartext index recovery on reindexing with stashed session keys" +notmuch restore <<EOF +#notmuch-dump batch-tag:3 config,properties,tags +#= simple-encrypted@crypto.notmuchmail.org session-key=9%3AFC09987F5F927CC0CC0EE80A96E4C5BBF4A499818FB591207705DFDDD6112CF9 +EOF +notmuch reindex id:simple-encrypted@crypto.notmuchmail.org +output=$(notmuch search sekrit) +expected='thread:0000000000000001 2016-12-22 [1/1] Daniel Kahn Gillmor; encrypted message (encrypted inbox unread)' +if [ $NOTMUCH_HAVE_GMIME_SESSION_KEYS -eq 0 ]; then + test_subtest_known_broken +fi +test_expect_equal \ + "$output" \ + "$expected" + +test_begin_subtest "notmuch reply should show cleartext if session key is present" +output=$(notmuch reply id:simple-encrypted@crypto.notmuchmail.org | grep '^>') +expected='> This is a top sekrit message.' +if [ $NOTMUCH_HAVE_GMIME_SESSION_KEYS -eq 0 ]; then + test_subtest_known_broken +fi +test_expect_equal \ + "$output" \ + "$expected" + +test_begin_subtest "notmuch show should show cleartext if session key is present" +output=$(notmuch show id:simple-encrypted@crypto.notmuchmail.org | awk '/^\014part}/{ f=0 }; { if (f) { print $0 } } /^\014part{ ID: 3/{ f=1 }') +expected='This is a top sekrit message.' +if [ $NOTMUCH_HAVE_GMIME_SESSION_KEYS -eq 0 ]; then + test_subtest_known_broken +fi +test_expect_equal \ + "$output" \ + "$expected" + +test_begin_subtest "notmuch show should show nothing if decryption is explicitly disallowed" +output=$(notmuch show --decrypt=false id:simple-encrypted@crypto.notmuchmail.org | awk '/^\014part}/{ f=0 }; { if (f) { print $0 } } /^\014part{ ID: 3/{ f=1 }') +expected='Non-text part: application/octet-stream' +test_expect_equal \ + "$output" \ + "$expected" + +test_begin_subtest "purging stashed session keys should lose access to the cleartext" +notmuch reindex --decrypt=false id:simple-encrypted@crypto.notmuchmail.org +output=$(notmuch search sekrit) +expected='' +test_expect_equal \ + "$output" \ + "$expected" + +test_begin_subtest "and cleartext should be unrecoverable now that there are no stashed session keys" +notmuch dump +notmuch reindex --decrypt=true id:simple-encrypted@crypto.notmuchmail.org +output=$(notmuch search sekrit) +expected='' +test_expect_equal \ + "$output" \ + "$expected" + + +# TODO: test removal of a message from the message store between +# indexing and reindexing. + +# TODO: insert the same message into the message store twice, index, +# remove one of them from the message store, and then reindex. +# reindexing should return a failure but the message should still be +# present? -- or what should the semantics be if you ask to reindex a +# message whose underlying files have been renamed or moved or +# removed? + +test_done diff --git a/test/T360-symbol-hiding.sh b/test/T360-symbol-hiding.sh index 9c6d4e64..43921cb4 100755 --- a/test/T360-symbol-hiding.sh +++ b/test/T360-symbol-hiding.sh @@ -9,7 +9,7 @@ test_description='exception symbol hiding' -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 test_begin_subtest 'running test' run_test mkdir -p ${PWD}/fakedb/.notmuch @@ -26,8 +26,8 @@ test_begin_subtest 'checking output' test_expect_equal "$result" "$output" test_begin_subtest 'comparing existing to exported symbols' -nm -P $TEST_DIRECTORY/../lib/libnotmuch.so | awk '$2 == "T" && $1 ~ "^notmuch" {print $1}' | sort | uniq > ACTUAL -sed -n 's/^\(notmuch_[a-zA-Z0-9_]*\)[[:blank:]]*(.*/\1/p' $TEST_DIRECTORY/../lib/notmuch.h | sort | uniq > EXPORTED +nm -P $NOTMUCH_BUILDDIR/lib/libnotmuch.so | awk '$2 == "T" && $1 ~ "^notmuch" {print $1}' | sort | uniq > ACTUAL +sed -n 's/^\(notmuch_[a-zA-Z0-9_]*\)[[:blank:]]*(.*/\1/p' $NOTMUCH_SRCDIR/lib/notmuch.h | sort | uniq > EXPORTED test_expect_equal_file EXPORTED ACTUAL test_done diff --git a/test/T370-search-folder-coherence.sh b/test/T370-search-folder-coherence.sh index d1cb45ec..0a2727e7 100755 --- a/test/T370-search-folder-coherence.sh +++ b/test/T370-search-folder-coherence.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash test_description='folder tags removed and added through file renames remain consistent' -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 test_begin_subtest "No new messages" output=$(NOTMUCH_NEW) @@ -32,7 +32,7 @@ test_expect_equal_file EXPECTED OUTPUT test_begin_subtest "Test matches folder:spam" output=$(notmuch search folder:spam) -test_expect_equal "$output" "thread:0000000000000001 2001-01-05 [1/1] Notmuch Test Suite; Single new message (inbox unread)" +test_expect_equal "$output" "thread:0000000000000001 2001-01-05 [1/1(2)] 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/T380-atomicity.sh b/test/T380-atomicity.sh index a46a2df2..45de2228 100755 --- a/test/T380-atomicity.sh +++ b/test/T380-atomicity.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash test_description='atomicity' -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 # This script tests the effects of killing and restarting "notmuch # new" at arbitrary points. If notmuch new is properly atomic, the @@ -64,7 +64,7 @@ if test_require_external_prereq gdb; then # -tty /dev/null works around a conflict between the 'timeout' wrapper # and gdb's attempt to control the TTY. export MAIL_DIR - ${TEST_GDB} -tty /dev/null -batch -x $TEST_DIRECTORY/atomicity.py notmuch 1>gdb.out 2>&1 + ${TEST_GDB} -tty /dev/null -batch -x $NOTMUCH_SRCDIR/test/atomicity.py notmuch 1>gdb.out 2>&1 # Get the final, golden output notmuch search '*' > expected diff --git a/test/T390-python.sh b/test/T390-python.sh index a9a61145..9f71ce3c 100755 --- a/test/T390-python.sh +++ b/test/T390-python.sh @@ -1,10 +1,11 @@ #!/usr/bin/env bash test_description="python bindings" -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 test_require_external_prereq ${NOTMUCH_PYTHON} add_email_corpus +add_gnupg_home test_begin_subtest "compare thread ids" test_python <<EOF @@ -56,5 +57,141 @@ grep '^[0-9a-f]' OUTPUT > INITIAL_OUTPUT test_begin_subtest "output of count matches test code" notmuch count --lastmod '*' | cut -f2-3 > OUTPUT test_expect_equal_file INITIAL_OUTPUT OUTPUT +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 +test_begin_subtest "Add ISO-8859-2 encoded message, call get_message_parts" +test_python <<EOF +import notmuch +db = notmuch.Database(mode=notmuch.Database.MODE.READ_ONLY) +q_new = notmuch.Query(db, 'ISO-8859-2 encoded message') +for m in q_new.search_messages(): + for mp in m.get_message_parts(): + continue + print(m.get_message_id()) +EOF + +notmuch search --sort=oldest-first --output=messages "tučňáččí" | sed s/^id:// > EXPECTED +test_expect_equal_file EXPECTED OUTPUT + +# TODO currently these tests for setting and getting config values are +# somewhat interdependent. This is because the config values stored in the +# database are not cleaned up after each test, so they remain there for the +# next test. The ./README file states that this can happen so it seems kind +# of ok. + +test_begin_subtest "set and get config values" +test_python <<'EOF' +import notmuch +db = notmuch.Database(mode=notmuch.Database.MODE.READ_WRITE) +db.set_config('testkey1', 'testvalue1') +db.set_config('testkey2', 'testvalue2') +v1 = db.get_config('testkey1') +v2 = db.get_config('testkey2') +print('testkey1 = ' + v1) +print('testkey2 = ' + v2) +EOF +cat <<'EOF' >EXPECTED +testkey1 = testvalue1 +testkey2 = testvalue2 +EOF +test_expect_equal_file EXPECTED OUTPUT + +test_begin_subtest "get_configs with no match returns empty generator" +test_python <<'EOF' +import notmuch +db = notmuch.Database() +v = db.get_configs('nonexistent') +print(list(v) == []) +EOF +test_expect_equal "$(cat OUTPUT)" "True" + +test_begin_subtest "get_configs with no arguments returns all pairs" +test_python <<'EOF' +import notmuch +db = notmuch.Database(mode=notmuch.Database.MODE.READ_WRITE) +db.set_config("zzzafter", "afterval") +db.set_config("aaabefore", "beforeval") +v = db.get_configs() +for index, keyval in enumerate(v): + key, val = keyval + print('{}: {} => {}'.format(index, key, val)) +EOF +cat <<'EOF' >EXPECTED +0: aaabefore => beforeval +1: testkey1 => testvalue1 +2: testkey2 => testvalue2 +3: zzzafter => afterval +EOF +test_expect_equal_file EXPECTED OUTPUT + +test_begin_subtest "get_configs prefix is used to match keys" +test_python <<'EOF' +import notmuch +db = notmuch.Database(mode=notmuch.Database.MODE.READ_WRITE) +db.set_config('testkey1', 'testvalue1') +db.set_config('testkey2', 'testvalue2') +v = db.get_configs('testkey') +for index, keyval in enumerate(v): + key, val = keyval + print('{}: {} => {}'.format(index, key, val)) +EOF +cat <<'EOF' >EXPECTED +0: testkey1 => testvalue1 +1: testkey2 => testvalue2 +EOF +test_expect_equal_file EXPECTED OUTPUT + +test_begin_subtest "set_config with no value will unset config entries" +test_python <<'EOF' +import notmuch +db = notmuch.Database(mode=notmuch.Database.MODE.READ_WRITE) +db.set_config('testkey1', '') +db.set_config('testkey2', '') +db.set_config("zzzafter", '') +db.set_config("aaabefore", '') +v = db.get_configs() +print(list(v) == []) +EOF +test_expect_equal "$(cat OUTPUT)" "True" + +mkdir -p "${MAIL_DIR}/cur" +fname="${MAIL_DIR}/cur/simplemsg.eml" +cat <<EOF > "$fname" +From: test_suite@notmuchmail.org +To: test_suite@notmuchmail.org +Subject: encrypted message +Date: Sat, 01 Jan 2000 12:00:00 +0000 +Message-ID: <simplemsg@crypto.notmuchmail.org> +MIME-Version: 1.0 +Content-Type: multipart/encrypted; boundary="=-=-="; + protocol="application/pgp-encrypted" + +--=-=-= +Content-Type: application/pgp-encrypted + +Version: 1 + +--=-=-= +Content-Type: application/octet-stream + +$(printf 'Content-Type: text/plain\n\nThis is the sekrit message\n' | gpg --no-tty --batch --quiet --trust-model=always --encrypt --armor --recipient test_suite@notmuchmail.org) +--=-=-=-- +EOF + +test_begin_subtest "index message with decryption" +test_python <<EOF +import notmuch +db = notmuch.Database(mode=notmuch.Database.MODE.READ_WRITE) +(m, status) = db.index_file('$fname', decrypt_policy=notmuch.Database.DECRYPTION_POLICY.TRUE) +if status == notmuch.errors.STATUS.DUPLICATE_MESSAGE_ID: + print("got duplicate message") +q_new = notmuch.Query(db, 'sekrit') +for m in q_new.search_messages(): + print(m.get_filename()) +EOF +echo "$fname" > EXPECTED +test_expect_equal_file EXPECTED OUTPUT test_done diff --git a/test/T395-ruby.sh b/test/T395-ruby.sh index 52f9fe0f..a0b76eb8 100755 --- a/test/T395-ruby.sh +++ b/test/T395-ruby.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash test_description="ruby bindings" -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 if [ "${NOTMUCH_HAVE_RUBY_DEV}" = "0" ]; then test_subtest_missing_external_prereq_["ruby development files"]=t diff --git a/test/T400-hooks.sh b/test/T400-hooks.sh index 7917a82f..49c690eb 100755 --- a/test/T400-hooks.sh +++ b/test/T400-hooks.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash test_description='hooks' -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 HOOK_DIR=${MAIL_DIR}/.notmuch/hooks diff --git a/test/T410-argument-parsing.sh b/test/T410-argument-parsing.sh index fad134e3..a384ce86 100755 --- a/test/T410-argument-parsing.sh +++ b/test/T410-argument-parsing.sh @@ -1,10 +1,11 @@ #!/usr/bin/env bash test_description="argument parsing" -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 test_begin_subtest "sanity check" -$TEST_DIRECTORY/arg-test pos1 --keyword=one --string=foo pos2 --int=7 --flag=one --flag=three > OUTPUT +$TEST_DIRECTORY/arg-test pos1 --keyword=one --boolean --string=foo pos2 --int=7 --flag=one --flag=three > OUTPUT cat <<EOF > EXPECTED +boolean 1 keyword 1 flags 5 int 7 @@ -14,4 +15,86 @@ positional arg 2 pos2 EOF test_expect_equal_file EXPECTED OUTPUT +test_begin_subtest "sanity check zero values" +$TEST_DIRECTORY/arg-test --keyword=zero --boolean=false --int=0 > OUTPUT +cat <<EOF > EXPECTED +boolean 0 +keyword 0 +int 0 +EOF +test_expect_equal_file EXPECTED OUTPUT + +test_begin_subtest "space instead of = between parameter name and value" +# Note: spaces aren't allowed for booleans. false turns into a positional arg! +$TEST_DIRECTORY/arg-test --keyword one --boolean false --string foo --int 7 --flag one --flag three > OUTPUT +cat <<EOF > EXPECTED +boolean 1 +keyword 1 +flags 5 +int 7 +string foo +positional arg 1 false +EOF +test_expect_equal_file EXPECTED OUTPUT + +test_begin_subtest "--boolean=true" +$TEST_DIRECTORY/arg-test --boolean=true > OUTPUT +cat <<EOF > EXPECTED +boolean 1 +EOF +test_expect_equal_file EXPECTED OUTPUT + +test_begin_subtest "--boolean=false" +$TEST_DIRECTORY/arg-test --boolean=false > OUTPUT +cat <<EOF > EXPECTED +boolean 0 +EOF +test_expect_equal_file EXPECTED OUTPUT + +test_begin_subtest "--no-boolean" +$TEST_DIRECTORY/arg-test --no-boolean > OUTPUT +cat <<EOF > EXPECTED +boolean 0 +EOF +test_expect_equal_file EXPECTED OUTPUT + +test_begin_subtest "--no-flag" +$TEST_DIRECTORY/arg-test --flag=one --flag=three --no-flag=three > OUTPUT +cat <<EOF > EXPECTED +flags 1 +EOF +test_expect_equal_file EXPECTED OUTPUT + +test_begin_subtest "test keyword arguments without value" +$TEST_DIRECTORY/arg-test --boolkeyword bananas > OUTPUT +cat <<EOF > EXPECTED +boolkeyword 1 +positional arg 1 bananas +EOF +test_expect_equal_file EXPECTED OUTPUT + +test_begin_subtest "test keyword arguments with non-default value separted by a space" +$TEST_DIRECTORY/arg-test --boolkeyword false bananas > OUTPUT +cat <<EOF > EXPECTED +boolkeyword 0 +positional arg 1 bananas +EOF +test_expect_equal_file EXPECTED OUTPUT + +test_begin_subtest "test keyword arguments without value at the end" +$TEST_DIRECTORY/arg-test bananas --boolkeyword > OUTPUT +cat <<EOF > EXPECTED +boolkeyword 1 +positional arg 1 bananas +EOF +test_expect_equal_file EXPECTED OUTPUT + +test_begin_subtest "test keyword arguments without value but with = (should be an error)" +$TEST_DIRECTORY/arg-test bananas --boolkeyword= > OUTPUT 2>&1 +cat <<EOF > EXPECTED +Unknown keyword argument "" for option "boolkeyword". +Unrecognized option: --boolkeyword= +EOF +test_expect_equal_file EXPECTED OUTPUT + test_done diff --git a/test/T420-emacs-test-functions.sh b/test/T420-emacs-test-functions.sh index 955c5f7f..bfc10be3 100755 --- a/test/T420-emacs-test-functions.sh +++ b/test/T420-emacs-test-functions.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash test_description="emacs test function sanity" -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 test_begin_subtest "emacs test function sanity" test_emacs_expect_t 't' diff --git a/test/T430-emacs-address-cleaning.sh b/test/T430-emacs-address-cleaning.sh index 664b79d2..02d3b411 100755 --- a/test/T430-emacs-address-cleaning.sh +++ b/test/T430-emacs-address-cleaning.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash test_description="emacs address cleaning" -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 test_begin_subtest "notmuch-test-address-clean part 1" test_emacs_expect_t '(notmuch-test-address-cleaning-1)' diff --git a/test/T440-emacs-hello.sh b/test/T440-emacs-hello.sh index ac214a5b..d23c1fca 100755 --- a/test/T440-emacs-hello.sh +++ b/test/T440-emacs-hello.sh @@ -1,9 +1,9 @@ #!/usr/bin/env bash test_description="emacs notmuch-hello view" -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 -EXPECTED=$TEST_DIRECTORY/emacs.expected-output +EXPECTED=$NOTMUCH_SRCDIR/test/emacs.expected-output add_email_corpus diff --git a/test/T450-emacs-show.sh b/test/T450-emacs-show.sh index db48c7d5..3555a939 100755 --- a/test/T450-emacs-show.sh +++ b/test/T450-emacs-show.sh @@ -1,9 +1,9 @@ #!/usr/bin/env bash test_description="emacs notmuch-show view" -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 -EXPECTED=$TEST_DIRECTORY/emacs-show.expected-output +EXPECTED=$NOTMUCH_SRCDIR/test/emacs-show.expected-output add_email_corpus @@ -191,12 +191,21 @@ This is an error (see *Notmuch errors* for more details) === ERROR === [XXX] This is an error -command: YYY/notmuch_fail show --format\\=sexp --format-version\\=4 --decrypt --exclude\\=false \\' \\* \\' +command: YYY/notmuch_fail show --format\\=sexp --format-version\\=4 --decrypt\\=true --exclude\\=false \\' \\* \\' exit status: 1 stderr: This is an error stdout: This is output" +test_begin_subtest "text/enriched exploit mitigation" +add_message '[content-type]="text/enriched" + [body]=" +<x-display><param>(when (progn (read-only-mode -1) (insert ?p ?0 ?w ?n ?e ?d)) nil)</param>test</x-display> +"' +test_emacs '(notmuch-show "id:'$gen_msg_id'") + (test-visible-output "OUTPUT.raw")' +output=$(head -1 OUTPUT.raw|cut -f1-4 -d' ') +test_expect_equal "$output" "Notmuch Test Suite <test_suite@notmuchmail.org>" test_done diff --git a/test/T455-emacs-charsets.sh b/test/T455-emacs-charsets.sh index 5d6d53a8..cb1297ca 100755 --- a/test/T455-emacs-charsets.sh +++ b/test/T455-emacs-charsets.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash test_description="emacs notmuch-show charset handling" -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 UTF8_YEN=$'\xef\xbf\xa5' diff --git a/test/T460-emacs-tree.sh b/test/T460-emacs-tree.sh index 958ff888..0f4e4503 100755 --- a/test/T460-emacs-tree.sh +++ b/test/T460-emacs-tree.sh @@ -1,9 +1,9 @@ #!/usr/bin/env bash test_description="emacs tree view interface" -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 -EXPECTED=$TEST_DIRECTORY/tree.expected-output +EXPECTED=$NOTMUCH_SRCDIR/test/tree.expected-output add_email_corpus diff --git a/test/T470-missing-headers.sh b/test/T470-missing-headers.sh index 32031e31..555fd4e9 100755 --- a/test/T470-missing-headers.sh +++ b/test/T470-missing-headers.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash test_description='messages with missing headers' -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 # Notmuch requires at least one of from, subject, or to or it will # ignore the file. Generate two messages so that together they cover @@ -25,7 +25,7 @@ NOTMUCH_NEW >/dev/null test_begin_subtest "Search: text" output=$(notmuch search '*' | notmuch_search_sanitize) test_expect_equal "$output" "\ -thread:XXX 2001-01-05 [1/1] (null); (inbox unread) +thread:XXX 2001-01-05 [1/1] ; (inbox unread) thread:XXX 1970-01-01 [1/1] Notmuch Test Suite; (inbox unread)" test_begin_subtest "Search: json" diff --git a/test/T480-hex-escaping.sh b/test/T480-hex-escaping.sh index 86cf3729..2c5bbb63 100755 --- a/test/T480-hex-escaping.sh +++ b/test/T480-hex-escaping.sh @@ -1,9 +1,9 @@ #!/usr/bin/env bash test_description="hex encoding and decoding" -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 test_begin_subtest "round trip" -find $TEST_DIRECTORY/corpus -type f -print | sort | xargs cat > EXPECTED +find $NOTMUCH_SRCDIR/test/corpora/default -type f -print | sort | xargs cat > EXPECTED $TEST_DIRECTORY/hex-xcode --direction=encode < EXPECTED | $TEST_DIRECTORY/hex-xcode --direction=decode > OUTPUT test_expect_equal_file EXPECTED OUTPUT @@ -25,7 +25,7 @@ $TEST_DIRECTORY/hex-xcode --direction=decode < EXPECTED.$test_count |\ test_expect_equal_file EXPECTED.$test_count OUTPUT.$test_count test_begin_subtest "round trip (in-place)" -find $TEST_DIRECTORY/corpus -type f -print | sort | xargs cat > EXPECTED +find $NOTMUCH_SRCDIR/test/corpora/default -type f -print | sort | xargs cat > EXPECTED $TEST_DIRECTORY/hex-xcode --in-place --direction=encode < EXPECTED |\ $TEST_DIRECTORY/hex-xcode --in-place --direction=decode > OUTPUT test_expect_equal_file EXPECTED OUTPUT diff --git a/test/T490-parse-time-string.sh b/test/T490-parse-time-string.sh index ab90fcc5..d1c70cfa 100755 --- a/test/T490-parse-time-string.sh +++ b/test/T490-parse-time-string.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash test_description="date/time parser module" -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 # Sanity/smoke tests for the date/time parser independent of notmuch diff --git a/test/T500-search-date.sh b/test/T500-search-date.sh index f10207f8..f84b0962 100755 --- a/test/T500-search-date.sh +++ b/test/T500-search-date.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash test_description="date:since..until queries" -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 add_email_corpus @@ -12,18 +12,19 @@ test_begin_subtest "Absolute date range with 'same' operator" output=$(notmuch search date:2010-12-16..! | notmuch_search_sanitize) test_expect_equal "$output" "thread:XXX 2010-12-16 [1/1] Olivier Berger; Essai accentué (inbox unread)" -if [ "${NOTMUCH_HAVE_XAPIAN_FIELD_PROCESSOR}" = "1" ]; then - test_begin_subtest "Absolute date field" - output=$(notmuch search date:2010-12-16 | notmuch_search_sanitize) - test_expect_equal "$output" "thread:XXX 2010-12-16 [1/1] Olivier Berger; Essai accentué (inbox unread)" +test_begin_subtest "Absolute date field" +output=$(notmuch search date:2010-12-16 | notmuch_search_sanitize) +if [ $NOTMUCH_HAVE_XAPIAN_FIELD_PROCESSOR -ne 1 ]; then + test_subtest_known_broken fi +test_expect_equal "$output" "thread:XXX 2010-12-16 [1/1] Olivier Berger; Essai accentué (inbox unread)" test_begin_subtest "Absolute time range with TZ" notmuch search date:18-Nov-2009_02:19:26-0800..2009-11-18_04:49:52-06:00 | notmuch_search_sanitize > OUTPUT cat <<EOF >EXPECTED thread:XXX 2009-11-18 [1/3] Carl Worth| Jan Janak; [notmuch] What a great idea! (inbox unread) thread:XXX 2009-11-18 [1/2] Carl Worth| Jan Janak; [notmuch] [PATCH] Older versions of install do not support -C. (inbox unread) -thread:XXX 2009-11-18 [1/3] Carl Worth| Aron Griffis, Keith Packard; [notmuch] archive (inbox unread) +thread:XXX 2009-11-18 [1/3(4)] Carl Worth| Aron Griffis, Keith Packard; [notmuch] archive (inbox unread) thread:XXX 2009-11-18 [1/2] Carl Worth| Keith Packard; [notmuch] [PATCH] Make notmuch-show 'X' (and 'x') commands remove inbox (and unread) tags (inbox unread) EOF test_expect_equal_file EXPECTED OUTPUT diff --git a/test/T510-thread-replies.sh b/test/T510-thread-replies.sh index fa288bb1..6837ff17 100755 --- a/test/T510-thread-replies.sh +++ b/test/T510-thread-replies.sh @@ -9,7 +9,7 @@ test_description='test of proper handling of in-reply-to and references headers' # database is constructed properly, even in the presence of # non-RFC-compliant headers' -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 test_begin_subtest "Use References when In-Reply-To is broken" add_message '[id]="foo@one.com"' \ diff --git a/test/T520-show.sh b/test/T520-show.sh index fb232a32..16222650 100755 --- a/test/T520-show.sh +++ b/test/T520-show.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash test_description='"notmuch show"' -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 add_email_corpus diff --git a/test/T530-upgrade.sh b/test/T530-upgrade.sh index f0fd1511..69ebec68 100755 --- a/test/T530-upgrade.sh +++ b/test/T530-upgrade.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash test_description="database upgrade" -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 dbtarball=database-v1.tar.xz diff --git a/test/T550-db-features.sh b/test/T550-db-features.sh index f94a660d..9d5a9e70 100755 --- a/test/T550-db-features.sh +++ b/test/T550-db-features.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash test_description="database version and feature compatibility" -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 test_begin_subtest "future database versions abort open" ${TEST_DIRECTORY}/make-db-version ${MAIL_DIR} 9999 "" diff --git a/test/T560-lib-error.sh b/test/T560-lib-error.sh index 34d15698..06a6b860 100755 --- a/test/T560-lib-error.sh +++ b/test/T560-lib-error.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash test_description="error reporting for library" -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 add_email_corpus @@ -127,7 +127,7 @@ int main (int argc, char** argv) if (stat != NOTMUCH_STATUS_SUCCESS) { fprintf (stderr, "error opening database: %d\n", stat); } - stat = notmuch_database_add_message (db, "/dev/null", NULL); + stat = notmuch_database_index_file (db, "/dev/null", NULL, NULL); if (stat) fputs (notmuch_database_status_string (db), stderr); @@ -152,7 +152,7 @@ int main (int argc, char** argv) if (stat != NOTMUCH_STATUS_SUCCESS) { fprintf (stderr, "error opening database: %d\n", stat); } - stat = notmuch_database_add_message (db, "./nonexistent", NULL); + stat = notmuch_database_index_file (db, "./nonexistent", NULL, NULL); if (stat) { char *status_string = notmuch_database_status_string (db); if (status_string) fputs (status_string, stderr); diff --git a/test/T570-revision-tracking.sh b/test/T570-revision-tracking.sh index 76ad2279..a59e7c98 100755 --- a/test/T570-revision-tracking.sh +++ b/test/T570-revision-tracking.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash test_description="database revision tracking" -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 add_email_corpus diff --git a/test/T580-thread-search.sh b/test/T580-thread-search.sh index 512559a3..01aa3efd 100755 --- a/test/T580-thread-search.sh +++ b/test/T580-thread-search.sh @@ -5,7 +5,7 @@ test_description='test of searching by thread-id' -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 add_email_corpus diff --git a/test/T590-libconfig.sh b/test/T590-libconfig.sh index 1b308693..46f3a76d 100755 --- a/test/T590-libconfig.sh +++ b/test/T590-libconfig.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash test_description="library config API" -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 add_email_corpus diff --git a/test/T590-thread-breakage.sh b/test/T590-thread-breakage.sh index 38abc211..aeb82cf4 100755 --- a/test/T590-thread-breakage.sh +++ b/test/T590-thread-breakage.sh @@ -19,7 +19,7 @@ test_description='thread breakage during reindexing' # works properly and attempted fixes to threading issues do not break # the expected contents of the index. -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 message_a() { mkdir -p ${MAIL_DIR}/cur @@ -66,7 +66,7 @@ test_thread_count() { test_ghost_count() { test_begin_subtest "${2:-Expecting $1 ghosts(s)}" - ghosts=$(../ghost-report ${MAIL_DIR}/.notmuch/xapian) + ghosts=$($NOTMUCH_BUILDDIR/test/ghost-report ${MAIL_DIR}/.notmuch/xapian) test_expect_equal "$ghosts" "$1" } @@ -111,7 +111,7 @@ test_content_count banana 0 test_begin_subtest 'No ghosts should remain after deletion of second message' # this is known to fail; we are leaking ghost messages deliberately test_subtest_known_broken -ghosts=$(../ghost-report ${MAIL_DIR}/.notmuch/xapian) +ghosts=$($NOTMUCH_BUILDDIR/test/ghost-report ${MAIL_DIR}/.notmuch/xapian) test_expect_equal "$ghosts" "0" rm -f ${MAIL_DIR}/cur/a diff --git a/test/T600-named-queries.sh b/test/T600-named-queries.sh index 495b7699..abaee3b7 100755 --- a/test/T600-named-queries.sh +++ b/test/T600-named-queries.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash test_description='named queries' -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 QUERYSTR="date:2009-11-18..2009-11-18 and tag:unread" @@ -50,21 +50,25 @@ notmuch restore < BEFORE notmuch dump | grep '^#@' > OUTPUT test_expect_equal_file QUERIES.BEFORE OUTPUT -if [ $NOTMUCH_HAVE_XAPIAN_FIELD_PROCESSOR -eq 1 ]; then - test_begin_subtest "search named query" - notmuch search query:test > OUTPUT - notmuch search $QUERYSTR > EXPECTED - test_expect_equal_file EXPECTED OUTPUT - - test_begin_subtest "search named query with other terms" - notmuch search query:test and subject:Maildir > OUTPUT - notmuch search $QUERYSTR and subject:Maildir > EXPECTED - test_expect_equal_file EXPECTED OUTPUT +test_begin_subtest "search named query" +notmuch search query:test > OUTPUT +notmuch search $QUERYSTR > EXPECTED +if [ $NOTMUCH_HAVE_XAPIAN_FIELD_PROCESSOR -ne 1 ]; then + test_subtest_known_broken +fi +test_expect_equal_file EXPECTED OUTPUT - test_begin_subtest "search nested named query" - notmuch search query:test2 > OUTPUT - notmuch search $QUERYSTR2 > EXPECTED - test_expect_equal_file EXPECTED OUTPUT +test_begin_subtest "search named query with other terms" +notmuch search query:test and subject:Maildir > OUTPUT +notmuch search $QUERYSTR and subject:Maildir > EXPECTED +if [ $NOTMUCH_HAVE_XAPIAN_FIELD_PROCESSOR -ne 1 ]; then + test_subtest_known_broken fi +test_expect_equal_file EXPECTED OUTPUT + +test_begin_subtest "search nested named query" +notmuch search query:test2 > OUTPUT +notmuch search $QUERYSTR2 > EXPECTED +test_expect_equal_file EXPECTED OUTPUT test_done diff --git a/test/T610-message-property.sh b/test/T610-message-property.sh index ba5f55da..74b3f5a1 100755 --- a/test/T610-message-property.sh +++ b/test/T610-message-property.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash test_description="message property API" -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 add_email_corpus diff --git a/test/T620-lock.sh b/test/T620-lock.sh index f46475e8..7aaaff2a 100755 --- a/test/T620-lock.sh +++ b/test/T620-lock.sh @@ -1,14 +1,13 @@ #!/usr/bin/env bash test_description="locking" -. ./test-lib.sh || exit 1 - -if [ "${NOTMUCH_HAVE_XAPIAN_DB_RETRY_LOCK}" = "0" ]; then - test_subtest_missing_external_prereq_["lock retry support"]=t -fi +. $(dirname "$0")/test-lib.sh || exit 1 add_email_corpus test_begin_subtest "blocking open" +if [ $NOTMUCH_HAVE_XAPIAN_DB_RETRY_LOCK -ne 1 ]; then + test_subtest_known_broken +fi test_C ${MAIL_DIR} <<'EOF' #include <unistd.h> #include <stdlib.h> @@ -70,6 +69,9 @@ inbox parent unread EOF +if [ $NOTMUCH_HAVE_XAPIAN_DB_RETRY_LOCK -ne 1 ]; then + test_subtest_known_broken +fi test_expect_equal_file EXPECTED OUTPUT test_done diff --git a/test/T630-emacs-draft.sh b/test/T630-emacs-draft.sh index cd9e33a7..d7903ce7 100755 --- a/test/T630-emacs-draft.sh +++ b/test/T630-emacs-draft.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash test_description="Emacs Draft Handling" -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 add_email_corpus diff --git a/test/T640-database-modified.sh b/test/T640-database-modified.sh index e35e35f6..274105c7 100755 --- a/test/T640-database-modified.sh +++ b/test/T640-database-modified.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash test_description="DatabaseModifiedError handling" -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 # add enough messages to trigger the exception add_email_corpus diff --git a/test/T650-regexp-query.sh b/test/T650-regexp-query.sh index b7bdda11..4085340f 100755 --- a/test/T650-regexp-query.sh +++ b/test/T650-regexp-query.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash test_description='regular expression searches' -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 if [ $NOTMUCH_HAVE_XAPIAN_FIELD_PROCESSOR -eq 0 ]; then test_done @@ -29,7 +29,7 @@ test_expect_equal_file EXPECTED OUTPUT test_begin_subtest "unanchored folder:// specification" output=$(notmuch search folder:/bad/ | notmuch_search_sanitize) test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; To the bone (inbox unread) -thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Bears (inbox unread) +thread:XXX 2001-01-05 [1/1(2)] Notmuch Test Suite; Bears (inbox unread) thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Bites, stings, sad feelings (inbox unread)" test_begin_subtest "anchored folder:// search" @@ -39,7 +39,7 @@ test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; T test_begin_subtest "unanchored path:// specification" output=$(notmuch search path:/bad/ | notmuch_search_sanitize) test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; To the bone (inbox unread) -thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Bears (inbox unread) +thread:XXX 2001-01-05 [1/1(2)] Notmuch Test Suite; Bears (inbox unread) thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Bites, stings, sad feelings (inbox unread)" test_begin_subtest "anchored path:// search" diff --git a/test/T660-bad-date.sh b/test/T660-bad-date.sh index a98e11c8..f65544b9 100755 --- a/test/T660-bad-date.sh +++ b/test/T660-bad-date.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash test_description="parsing of bad dates" -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 add_message [date]='"()"' diff --git a/test/T670-duplicate-mid.sh b/test/T670-duplicate-mid.sh new file mode 100755 index 00000000..c198c506 --- /dev/null +++ b/test/T670-duplicate-mid.sh @@ -0,0 +1,102 @@ +#!/usr/bin/env bash +test_description="duplicate message ids" +. $(dirname "$0")/test-lib.sh || exit 1 + +add_message '[id]="duplicate"' '[subject]="message 1" [filename]=copy1' +add_message '[id]="duplicate"' '[subject]="message 2" [filename]=copy2' + +add_message '[id]="duplicate"' '[subject]="message 0" [filename]=copy0' +test_begin_subtest 'search: first indexed subject preserved' +cat <<EOF > EXPECTED +thread:XXX 2001-01-05 [1/1(3)] Notmuch Test Suite; message 1 (inbox unread) +EOF +notmuch search id:duplicate | notmuch_search_sanitize > OUTPUT +test_expect_equal_file EXPECTED OUTPUT + +test_begin_subtest 'First subject preserved in notmuch-show (json)' +test_subtest_known_broken +output=$(notmuch show --body=false --format=json id:duplicate | notmuch_json_show_sanitize) +expected='[[[{ + "id": "XXXXX", + "match": true, + "excluded": false, + "filename": [ + "'"${MAIL_DIR}"/copy0'", + "'"${MAIL_DIR}"/copy1'", + "'"${MAIL_DIR}"/copy2'" + ], + "timestamp": 42, + "date_relative": "2001-01-05", + "tags": ["inbox","unread"], + "headers": { + "Subject": "message 1", + "From": "Notmuch Test Suite <test_suite@notmuchmail.org>", + "To": "Notmuch Test Suite <test_suite@notmuchmail.org>", + "Date": "GENERATED_DATE" + } + }, +[]]]]' +test_expect_equal_json "$output" "$expected" + +test_begin_subtest 'Search for second subject' +cat <<EOF >EXPECTED +MAIL_DIR/copy0 +MAIL_DIR/copy1 +MAIL_DIR/copy2 +EOF +notmuch search --output=files subject:'"message 2"' | notmuch_dir_sanitize > OUTPUT +test_expect_equal_file EXPECTED OUTPUT + +add_message '[id]="duplicate"' '[body]="sekrit" [filename]=copy3' +test_begin_subtest 'search for body in duplicate file' +cat <<EOF >EXPECTED +MAIL_DIR/copy0 +MAIL_DIR/copy1 +MAIL_DIR/copy2 +MAIL_DIR/copy3 +EOF +notmuch search --output=files "sekrit" | notmuch_dir_sanitize > OUTPUT +test_expect_equal_file EXPECTED OUTPUT + +rm ${MAIL_DIR}/copy3 +test_begin_subtest 'reindex drops terms in duplicate file' +cp /dev/null EXPECTED +notmuch reindex '*' +notmuch search --output=files "sekrit" | notmuch_dir_sanitize > OUTPUT +test_expect_equal_file EXPECTED OUTPUT + +test_begin_subtest 'reindex choses subject from first filename' +cat <<EOF > EXPECTED +thread:XXX 2001-01-05 [1/1(3)] Notmuch Test Suite; message 0 (inbox unread) +EOF +notmuch search id:duplicate | notmuch_search_sanitize > OUTPUT +test_expect_equal_file EXPECTED OUTPUT + +rm ${MAIL_DIR}/copy0 +test_begin_subtest 'Deleted first duplicate file does not stop notmuch show from working' +output=$(notmuch show --body=false --format=json id:duplicate | + notmuch_json_show_sanitize | sed 's/message [0-9]/A_SUBJECT/') +expected='[[[{ + "id": "XXXXX", + "match": true, + "excluded": false, + "filename": [ + "'"${MAIL_DIR}"/copy0'", + "'"${MAIL_DIR}"/copy1'", + "'"${MAIL_DIR}"/copy2'" + ], + "timestamp": 42, + "date_relative": "2001-01-05", + "tags": ["inbox","unread"], + "headers": { + "Subject": "A_SUBJECT", + "From": "Notmuch Test Suite <test_suite@notmuchmail.org>", + "To": "Notmuch Test Suite <test_suite@notmuchmail.org>", + "Date": "GENERATED_DATE" + } + }, +[]]]]' + +test_expect_equal_json "$output" "$expected" + +test_done diff --git a/test/T680-html-indexing.sh b/test/T680-html-indexing.sh index 74f33708..62ba8498 100755 --- a/test/T680-html-indexing.sh +++ b/test/T680-html-indexing.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash test_description="indexing of html parts" -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 add_email_corpus html diff --git a/test/T690-command-line-args.sh b/test/T690-command-line-args.sh index a4f4b5f5..9aa47611 100755 --- a/test/T690-command-line-args.sh +++ b/test/T690-command-line-args.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash test_description="command line arguments" -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 add_message diff --git a/test/T700-reindex.sh b/test/T700-reindex.sh new file mode 100755 index 00000000..2b7bc658 --- /dev/null +++ b/test/T700-reindex.sh @@ -0,0 +1,79 @@ +#!/usr/bin/env bash +test_description='reindexing messages' +. $(dirname "$0")/test-lib.sh || exit 1 + +add_email_corpus + +notmuch tag +usertag1 '*' + +notmuch search '*' | notmuch_search_sanitize > initial-threads +notmuch search --output=messages '*' > initial-message-ids +notmuch dump > initial-dump + +test_begin_subtest 'reindex preserves threads' +notmuch reindex '*' +notmuch search '*' | notmuch_search_sanitize > OUTPUT +test_expect_equal_file initial-threads OUTPUT + +test_begin_subtest 'reindex after removing duplicate file preserves threads' +# remove one copy +sed 's,3/3(4),3/3,' < initial-threads > EXPECTED +mv $MAIL_DIR/bar/18:2, duplicate-msg-1.eml +notmuch reindex '*' +notmuch search '*' | notmuch_search_sanitize > OUTPUT +test_expect_equal_file EXPECTED OUTPUT + +test_begin_subtest 'reindex preserves message-ids' +notmuch reindex '*' +notmuch search --output=messages '*' > OUTPUT +test_expect_equal_file initial-message-ids OUTPUT + +test_begin_subtest 'reindex preserves tags' +notmuch reindex '*' +notmuch dump > OUTPUT +test_expect_equal_file initial-dump OUTPUT + +test_begin_subtest 'reindex moves a message between threads' +notmuch search --output=threads id:87iqd9rn3l.fsf@vertex.dottedmag > EXPECTED +# re-parent +sed -i 's/1258471718-6781-1-git-send-email-dottedmag@dottedmag.net/87iqd9rn3l.fsf@vertex.dottedmag/' $MAIL_DIR/02:2,* +notmuch reindex id:1258471718-6781-2-git-send-email-dottedmag@dottedmag.net +notmuch search --output=threads id:1258471718-6781-2-git-send-email-dottedmag@dottedmag.net > OUTPUT +test_expect_equal_file EXPECTED OUTPUT + +test_begin_subtest 'reindex detects removal of all files' +notmuch search --output=messages not id:20091117232137.GA7669@griffis1.net> EXPECTED +# remove both copies +mv $MAIL_DIR/cur/51:2,* duplicate-message-2.eml +notmuch reindex id:20091117232137.GA7669@griffis1.net +notmuch search --output=messages '*' > OUTPUT +test_expect_equal_file EXPECTED OUTPUT + +test_begin_subtest "reindex preserves properties" +cat <<EOF > prop-dump +#= 1258471718-6781-1-git-send-email-dottedmag@dottedmag.net userprop=userval +#= 1258471718-6781-2-git-send-email-dottedmag@dottedmag.net userprop=userval +#= 1258491078-29658-1-git-send-email-dottedmag@dottedmag.net userprop=userval1 +#= 20091117190054.GU3165@dottiness.seas.harvard.edu userprop=userval +#= 20091117203301.GV3165@dottiness.seas.harvard.edu userprop=userval3 +#= 87fx8can9z.fsf@vertex.dottedmag userprop=userval2 +#= 87iqd9rn3l.fsf@vertex.dottedmag userprop=userval +#= 87lji4lx9v.fsf@yoom.home.cworth.org userprop=userval3 +#= 87lji5cbwo.fsf@yoom.home.cworth.org userprop=userval +#= cf0c4d610911171136h1713aa59w9cf9aa31f052ad0a@mail.gmail.com userprop=userval +EOF +notmuch restore < prop-dump +notmuch reindex '*' +notmuch dump | grep '^#=' | sort > OUTPUT +test_expect_equal_file prop-dump OUTPUT +test_done + +add_email_corpus lkml + +test_begin_subtest "reindex of lkml corpus preserves threads" +notmuch search '*' | notmuch_search_sanitize > EXPECTED +notmuch reindex '*' +notmuch search '*' | notmuch_search_sanitize > OUTPUT +test_expect_equal_file EXPECTED OUTPUT + +test_done diff --git a/test/arg-test.c b/test/arg-test.c index 736686de..a218f967 100644 --- a/test/arg-test.c +++ b/test/arg-test.c @@ -7,49 +7,73 @@ int main(int argc, char **argv){ int opt_index=1; int kw_val=0; + int kwb_val=0; int fl_val=0; int int_val=0; - char *pos_arg1=NULL; - char *pos_arg2=NULL; - char *string_val=NULL; + const char *pos_arg1=NULL; + const char *pos_arg2=NULL; + const char *string_val=NULL; + bool bool_val = false; + bool fl_set = false, int_set = false, bool_set = false, kwb_set = false, + kw_set = false, string_set = false, pos1_set = false, pos2_set = false; - notmuch_opt_desc_t options[] = { - { NOTMUCH_OPT_KEYWORD, &kw_val, "keyword", 'k', - (notmuch_keyword_t []){ { "one", 1 }, - { "two", 2 }, - { 0, 0 } } }, - { NOTMUCH_OPT_KEYWORD_FLAGS, &fl_val, "flag", 'f', + notmuch_opt_desc_t parent_options[] = { + { .opt_flags = &fl_val, .name = "flag", .present = &fl_set, .keywords = (notmuch_keyword_t []){ { "one", 1 << 0}, { "two", 1 << 1 }, { "three", 1 << 2 }, { 0, 0 } } }, - { NOTMUCH_OPT_INT, &int_val, "int", 'i', 0}, - { NOTMUCH_OPT_STRING, &string_val, "string", 's', 0}, - { NOTMUCH_OPT_POSITION, &pos_arg1, 0,0, 0}, - { NOTMUCH_OPT_POSITION, &pos_arg2, 0,0, 0}, - { 0, 0, 0, 0, 0 } }; + { .opt_int = &int_val, .name = "int", .present = &int_set }, + { } + }; + + notmuch_opt_desc_t options[] = { + { .opt_bool = &bool_val, .name = "boolean", .present = &bool_set }, + { .opt_keyword = &kw_val, .name = "keyword", .present = &kw_set, .keywords = + (notmuch_keyword_t []){ { "zero", 0 }, + { "one", 1 }, + { "two", 2 }, + { 0, 0 } } }, + { .opt_keyword = &kwb_val, .name = "boolkeyword", .present = &kwb_set, + .keyword_no_arg_value = "true", .keywords = + (notmuch_keyword_t []){ { "false", 0 }, + { "true", 1 }, + { "auto", 2 }, + { 0, 0 } } }, + { .opt_inherit = parent_options }, + { .opt_string = &string_val, .name = "string", .present = &string_set }, + { .opt_position = &pos_arg1, .present = &pos1_set }, + { .opt_position = &pos_arg2, .present = &pos2_set }, + { } + }; opt_index = parse_arguments(argc, argv, options, 1); if (opt_index < 0) return 1; - if (kw_val) + if (bool_set) + printf("boolean %d\n", bool_val); + + if (kw_set) printf("keyword %d\n", kw_val); - if (fl_val) + if (kwb_set) + printf("boolkeyword %d\n", kwb_val); + + if (fl_set) printf("flags %d\n", fl_val); - if (int_val) + if (int_set) printf("int %d\n", int_val); - if (string_val) + if (string_set) printf("string %s\n", string_val); - if (pos_arg1) + if (pos1_set) printf("positional arg 1 %s\n", pos_arg1); - if (pos_arg2) + if (pos2_set) printf("positional arg 2 %s\n", pos_arg2); diff --git a/test/corpora/README b/test/corpora/README index c9a35fed..05ea386d 100644 --- a/test/corpora/README +++ b/test/corpora/README @@ -12,3 +12,8 @@ broken html The html corpus contains html parts + +crypto + The crypto corpus contains encrypted messages for testing. + It should probably also contain signed messages in the future. + Please add them! diff --git a/test/corpora/crypto/simple-encrypted b/test/corpora/crypto/simple-encrypted new file mode 100644 index 00000000..6869972d --- /dev/null +++ b/test/corpora/crypto/simple-encrypted @@ -0,0 +1,36 @@ +From: Daniel Kahn Gillmor <dkg@fifthhorseman.net> +To: dkg@fifthhorseman.net +Subject: encrypted message +Date: Mon, 22 Dec 2016 08:34:56 -0400 +Message-ID: <simple-encrypted@crypto.notmuchmail.org> +MIME-Version: 1.0 +Content-Type: multipart/encrypted; boundary="=-=-="; + protocol="application/pgp-encrypted" + +--=-=-= +Content-Type: application/pgp-encrypted + +Version: 1 + +--=-=-= +Content-Type: application/octet-stream + +-----BEGIN PGP MESSAGE----- + +hQIMAzt6p/AU5ptaAQ/+IDRx5dZWKjUz9qITP76w8OvtmTV9p871UoGWil1DSd3J +dHgf56rXDWS73dzJ5EigevxLVMD3Xv8QEJBgMWb6yC+uR8ZdJ8h7hlE2lYyEg3Ch +smqzcaYp2nKWw9JZQqubsMaeIgVu0exb4YE8g/qlUOL2mD64dXhnkJ68GGMmiEPJ ++d0H7fTMwstbxvKPKDmFJUztH43V2NSfxpeQUTi4iWmQtUGw6THYjjAWNFy7jVEE +ozloT9W3ER5cRaXyKE4GWMBlUAOB0YwwsVnBU2JGUtTBzNHxQAbeoKrG6myrzmnC +LhUNag0gMuNEbGR78XfWKpCbccEC1VLf9uUXze6yeuRXDuhfsvilKOH9MpaR9n+G +JuYVAAobDc5wGOt5VGMka50ToaALrNt3FrWqni/0jqwqshEVKM3Kqzq6cSjh1TPf +pfxE9aUDdvf+Nn16ZBGgyLox2NV4GkSQYq2ySzAk3XwLU80F0nCmtOV3EH+OMrv6 +sZI/Svwzaqzrs/w17cvpf0czXjE/N9V1MHdNtIkfb707WkO0l9/wtYvlrg/KyrU2 +FH5aecEO9VpMumgzBqP1MrrnzVlSM3kgRLIu06oshQYD+jjFn2YzvkwZ+pWoAxsQ +ninQxoF8Ck2D7s8uGzx+HSQQpRVBM5AGfVdEkmzW/sZrlz63ZGUFh0FYqLl30rfS +cQGqSoZz0ugTSxnTlg0nuzFmG7ylC1cx3dlSrnfv+l1azwLAr58ptoYZ0mO+D+Fy +bePpCGoFAPKi0cZ/4eFlLKL7uYPmGeEo5Ku2wXU/SXtPfl4vRxzvPXTJTvD06vIx +Dh1P0ChAJtxUjGGY6xkCHMY0 +=frmz +-----END PGP MESSAGE----- +--=-=-=-- diff --git a/test/export-dirs.sh b/test/export-dirs.sh new file mode 100644 index 00000000..0578b1e5 --- /dev/null +++ b/test/export-dirs.sh @@ -0,0 +1,32 @@ +# Source this script to set and export NOTMUCH_SRCDIR and +# NOTMUCH_BUILDDIR. +# +# For this to work, always have current directory somewhere within the +# build directory hierarchy, and run the script sourcing this script +# using a path (relative or absolute) to the source directory. + +if [[ -z "${NOTMUCH_SRCDIR}" ]]; then + export NOTMUCH_SRCDIR="$(cd "$(dirname "$0")"/.. && pwd)" +fi + +find_builddir() +{ + local dir="$1" + + while [[ -n "$dir" ]] && [[ "$dir" != "/" ]]; do + if [[ -x "$dir/notmuch" ]] && [[ ! -d "$dir/notmuch" ]]; then + echo "$dir" + break + fi + dir="$(dirname "$dir")" + done +} + +if [[ -z "${NOTMUCH_BUILDDIR}" ]]; then + export NOTMUCH_BUILDDIR="$(find_builddir "$(pwd)")" + + if [[ -z "${NOTMUCH_BUILDDIR}" ]]; then + echo "Run tests in a subdir of built notmuch tree." >&2 + exit 1 + fi +fi diff --git a/test/hex-xcode.c b/test/hex-xcode.c index 65d49564..33046e9a 100644 --- a/test/hex-xcode.c +++ b/test/hex-xcode.c @@ -16,7 +16,7 @@ enum direction { DECODE }; -static int inplace = FALSE; +static bool inplace = false; static int xcode (void *ctx, enum direction dir, char *in, char **buf_p, size_t *size_p) @@ -44,17 +44,17 @@ int main (int argc, char **argv) { - enum direction dir = DECODE; - int omit_newline = FALSE; + int dir = DECODE; + bool omit_newline = false; notmuch_opt_desc_t options[] = { - { NOTMUCH_OPT_KEYWORD, &dir, "direction", 'd', + { .opt_keyword = &dir, .name = "direction", .keywords = (notmuch_keyword_t []){ { "encode", ENCODE }, { "decode", DECODE }, { 0, 0 } } }, - { NOTMUCH_OPT_BOOLEAN, &omit_newline, "omit-newline", 'n', 0 }, - { NOTMUCH_OPT_BOOLEAN, &inplace, "in-place", 'i', 0 }, - { 0, 0, 0, 0, 0 } + { .opt_bool = &omit_newline, .name = "omit-newline" }, + { .opt_bool = &inplace, .name = "in-place" }, + { } }; int opt_index = parse_arguments (argc, argv, options, 1); @@ -71,7 +71,7 @@ main (int argc, char **argv) char *buffer = NULL; size_t buf_size = 0; - notmuch_bool_t read_stdin = TRUE; + bool read_stdin = true; for (; opt_index < argc; opt_index++) { @@ -82,7 +82,7 @@ main (int argc, char **argv) if (! omit_newline) putchar ('\n'); - read_stdin = FALSE; + read_stdin = false; } if (! read_stdin) diff --git a/test/notmuch-test b/test/notmuch-test index e7d3151c..ca68dd41 100755 --- a/test/notmuch-test +++ b/test/notmuch-test @@ -15,12 +15,20 @@ if [ ${BASH_VERSINFO[0]} -lt 4 ]; then exit 1 fi -cd "$(dirname "$0")" +# Ensure NOTMUCH_SRCDIR and NOTMUCH_BUILDDIR are set. +. $(dirname "$0")/export-dirs.sh || exit 1 -TESTS=${NOTMUCH_TESTS:-T[0-9][0-9][0-9]-*.sh} +TESTS= +for test in $NOTMUCH_TESTS; do + TESTS="$TESTS $NOTMUCH_SRCDIR/test/$test" +done + +if [[ -z "$TESTS" ]]; then + TESTS="$NOTMUCH_SRCDIR/test/T[0-9][0-9][0-9]-*.sh" +fi # Clean up any results from a previous run -rm -rf test-results +rm -rf $NOTMUCH_BUILDDIR/test/test-results # Test for timeout utility if command -v timeout >/dev/null; then @@ -33,12 +41,13 @@ fi trap 'e=$?; kill $!; exit $e' HUP INT TERM # Run the tests for test in $TESTS; do - $TEST_TIMEOUT_CMD ./$test "$@" & + $TEST_TIMEOUT_CMD $test "$@" & wait $! # If the test failed without producing results, then it aborted, # so we should abort, too. RES=$? - if [[ $RES != 0 && ! -e "test-results/${test%.sh}" ]]; then + testname=$(basename $test .sh) + if [[ $RES != 0 && ! -e "$NOTMUCH_BUILDDIR/test/test-results/$testname" ]]; then exit $RES fi done @@ -46,10 +55,10 @@ trap - HUP INT TERM # Report results echo -./aggregate-results.sh test-results/* +$NOTMUCH_SRCDIR/test/aggregate-results.sh $NOTMUCH_BUILDDIR/test/test-results/* ev=$? # Clean up -rm -rf test-results corpus.mail +rm -rf $NOTMUCH_BUILDDIR/test/test-results $NOTMUCH_BUILDDIR/test/corpora.mail exit $ev diff --git a/test/random-corpus.c b/test/random-corpus.c index aca694a3..9272afda 100644 --- a/test/random-corpus.c +++ b/test/random-corpus.c @@ -116,10 +116,10 @@ random_utf8_string (void *ctx, size_t char_count) /* stubs since we cannot link with notmuch.o */ const notmuch_opt_desc_t notmuch_shared_options[] = { - { 0, 0, 0, 0, 0 } + { } }; -char *notmuch_requested_db_uuid = NULL; +const char *notmuch_requested_db_uuid = NULL; void notmuch_process_shared_options (unused (const char *dummy)) @@ -140,7 +140,7 @@ main (int argc, char **argv) void *ctx = talloc_new (NULL); - char *config_path = NULL; + const char *config_path = NULL; notmuch_config_t *config; notmuch_database_t *notmuch; @@ -155,13 +155,13 @@ main (int argc, char **argv) int seed = 734569; notmuch_opt_desc_t options[] = { - { NOTMUCH_OPT_STRING, &config_path, "config-path", 'c', 0 }, - { NOTMUCH_OPT_INT, &num_messages, "num-messages", 'n', 0 }, - { NOTMUCH_OPT_INT, &max_tags, "max-tags", 'm', 0 }, - { NOTMUCH_OPT_INT, &message_id_len, "message-id-len", 'M', 0 }, - { NOTMUCH_OPT_INT, &tag_len, "tag-len", 't', 0 }, - { NOTMUCH_OPT_INT, &seed, "seed", 's', 0 }, - { 0, 0, 0, 0, 0 } + { .opt_string = &config_path, .name = "config-path" }, + { .opt_int = &num_messages, .name = "num-messages" }, + { .opt_int = &max_tags, .name = "max-tags" }, + { .opt_int = &message_id_len, .name = "message-id-len" }, + { .opt_int = &tag_len, .name = "tag-len" }, + { .opt_int = &seed, .name = "seed" }, + { } }; int opt_index = parse_arguments (argc, argv, options, 1); @@ -179,7 +179,7 @@ main (int argc, char **argv) exit (1); } - config = notmuch_config_open (ctx, config_path, FALSE); + config = notmuch_config_open (ctx, config_path, false); if (config == NULL) return 1; diff --git a/test/smtp-dummy.c b/test/smtp-dummy.c index a629927c..71992edd 100644 --- a/test/smtp-dummy.c +++ b/test/smtp-dummy.c @@ -49,211 +49,226 @@ static void receive_data_to_file (FILE *peer, FILE *output) { - char *line = NULL; - size_t line_size; - ssize_t line_len; + char *line = NULL; + size_t line_size; + ssize_t line_len; - while ((line_len = getline (&line, &line_size, peer)) != -1) { - if (STRNCMP_LITERAL (line, ".\r\n") == 0) - break; - if (line_len < 2) - continue; - if (line[line_len-1] == '\n' && line[line_len-2] == '\r') { - line[line_len-2] = '\n'; - line[line_len-1] = '\0'; - } - fprintf (output, "%s", - line[0] == '.' ? line + 1 : line); + while ((line_len = getline (&line, &line_size, peer)) != -1) { + if (STRNCMP_LITERAL (line, ".\r\n") == 0) + break; + if (line_len < 2) + continue; + if (line[line_len - 1] == '\n' && line[line_len - 2] == '\r') { + line[line_len - 2] = '\n'; + line[line_len - 1] = '\0'; } + fprintf (output, "%s", + line[0] == '.' ? line + 1 : line); + } - free (line); + free (line); } static int process_command (FILE *peer, FILE *output, const char *command) { - if (STRNCMP_LITERAL (command, "EHLO ") == 0) { - fprintf (peer, "502 not implemented\r\n"); - fflush (peer); - } else if (STRNCMP_LITERAL (command, "HELO ") == 0) { - fprintf (peer, "250 localhost\r\n"); - fflush (peer); - } else if (STRNCMP_LITERAL (command, "MAIL FROM:") == 0 || - STRNCMP_LITERAL (command, "RCPT TO:") == 0) { - fprintf (peer, "250 OK\r\n"); - fflush (peer); - } else if (STRNCMP_LITERAL (command, "DATA") == 0) { - fprintf (peer, "354 End data with <CR><LF>.<CR><LF>\r\n"); - fflush (peer); - receive_data_to_file (peer, output); - fprintf (peer, "250 OK\r\n"); - fflush (peer); - } else if (STRNCMP_LITERAL (command, "QUIT") == 0) { - fprintf (peer, "221 BYE\r\n"); - fflush (peer); - return 1; - } else { - fprintf (stderr, "Unknown command: %s\n", command); - } - return 0; + if (STRNCMP_LITERAL (command, "EHLO ") == 0) { + fprintf (peer, "502 not implemented\r\n"); + fflush (peer); + } else if (STRNCMP_LITERAL (command, "HELO ") == 0) { + fprintf (peer, "250 localhost\r\n"); + fflush (peer); + } else if (STRNCMP_LITERAL (command, "MAIL FROM:") == 0 || + STRNCMP_LITERAL (command, "RCPT TO:") == 0) { + fprintf (peer, "250 OK\r\n"); + fflush (peer); + } else if (STRNCMP_LITERAL (command, "DATA") == 0) { + fprintf (peer, "354 End data with <CR><LF>.<CR><LF>\r\n"); + fflush (peer); + receive_data_to_file (peer, output); + fprintf (peer, "250 OK\r\n"); + fflush (peer); + } else if (STRNCMP_LITERAL (command, "QUIT") == 0) { + fprintf (peer, "221 BYE\r\n"); + fflush (peer); + return 1; + } else { + fprintf (stderr, "Unknown command: %s\n", command); + } + return 0; } static void do_smtp_to_file (FILE *peer, FILE *output) { - char *line = NULL; - size_t line_size; - ssize_t line_len; + char *line = NULL; + size_t line_size; + ssize_t line_len; - fprintf (peer, "220 localhost smtp-dummy\r\n"); - fflush (peer); + fprintf (peer, "220 localhost smtp-dummy\r\n"); + fflush (peer); - while ((line_len = getline (&line, &line_size, peer)) != -1) { - if (process_command (peer, output, line)) - break; - } + while ((line_len = getline (&line, &line_size, peer)) != -1) { + if (process_command (peer, output, line)) + break; + } - free (line); + free (line); } int main (int argc, char *argv[]) { - const char * progname; - char *output_filename; - FILE *peer_file, *output; - int sock, peer, err; - struct sockaddr_in addr, peer_addr; - struct hostent *hostinfo; - socklen_t peer_addr_len; - int reuse; - int background; + const char *progname; + char *output_filename; + FILE *peer_file = NULL, *output = NULL; + int sock = -1, peer, err; + struct sockaddr_in addr, peer_addr; + struct hostent *hostinfo; + socklen_t peer_addr_len; + int reuse; + int background; + int ret = 0; - progname = argv[0]; + progname = argv[0]; - background = 0; - for (; argc >= 2; argc--, argv++) { - if (argv[1][0] != '-') - break; - if (strcmp (argv[1], "--") == 0) { - argc--; - argv++; - break; - } - if (strcmp (argv[1], "--background") == 0) { - background = 1; - continue; - } - fprintf(stderr, "%s: unregognized option '%s'\n", - progname, argv[1]); - return 1; + background = 0; + for (; argc >= 2; argc--, argv++) { + if (argv[1][0] != '-') + break; + if (strcmp (argv[1], "--") == 0) { + argc--; + argv++; + break; } - - if (argc != 2) { - fprintf (stderr, - "Usage: %s [--background] <output-file>\n", progname); - return 1; + if (strcmp (argv[1], "--background") == 0) { + background = 1; + continue; } + fprintf (stderr, "%s: unregognized option '%s'\n", + progname, argv[1]); + return 1; + } - output_filename = argv[1]; - output = fopen (output_filename, "w"); - if (output == NULL) { - fprintf (stderr, "Failed to open %s for writing: %s\n", - output_filename, strerror (errno)); - return 1; - } + if (argc != 2) { + fprintf (stderr, + "Usage: %s [--background] <output-file>\n", progname); + return 1; + } - sock = socket (AF_INET, SOCK_STREAM, 0); - if (sock == -1) { - fprintf (stderr, "Error: socket() failed: %s\n", - strerror (errno)); - return 1; - } + output_filename = argv[1]; + output = fopen (output_filename, "w"); + if (output == NULL) { + fprintf (stderr, "Failed to open %s for writing: %s\n", + output_filename, strerror (errno)); + ret = 1; + goto DONE; + } - reuse = 1; - err = setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof (reuse)); - if (err) { - fprintf (stderr, "Error: setsockopt() failed: %s\n", - strerror (errno)); - return 1; - } + sock = socket (AF_INET, SOCK_STREAM, 0); + if (sock == -1) { + fprintf (stderr, "Error: socket() failed: %s\n", + strerror (errno)); + ret = 1; + goto DONE; + } - hostinfo = gethostbyname ("localhost"); - if (hostinfo == NULL) { - fprintf (stderr, "Unknown host: localhost\n"); - return 1; - } + reuse = 1; + err = setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof (reuse)); + if (err) { + fprintf (stderr, "Error: setsockopt() failed: %s\n", + strerror (errno)); + ret = 1; + goto DONE; + } - memset (&addr, 0, sizeof (addr)); - addr.sin_family = AF_INET; - addr.sin_port = htons (25025); - addr.sin_addr = *(struct in_addr *) hostinfo->h_addr; - err = bind (sock, (struct sockaddr *) &addr, sizeof(addr)); - if (err) { - fprintf (stderr, "Error: bind() failed: %s\n", - strerror (errno)); - close (sock); - return 1; - } + hostinfo = gethostbyname ("localhost"); + if (hostinfo == NULL) { + fprintf (stderr, "Unknown host: localhost\n"); + ret = 1; + goto DONE; + } - err = listen (sock, 1); - if (err) { - fprintf (stderr, "Error: listen() failed: %s\n", - strerror (errno)); - close (sock); - return 1; - } + memset (&addr, 0, sizeof (addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons (25025); + addr.sin_addr = *(struct in_addr *) hostinfo->h_addr; + err = bind (sock, (struct sockaddr *) &addr, sizeof (addr)); + if (err) { + fprintf (stderr, "Error: bind() failed: %s\n", + strerror (errno)); + close (sock); + ret = 1; + goto DONE; + } - if (background) { - int pid = fork (); - if (pid > 0) { - printf ("smtp_dummy_pid='%d'\n", pid); - fflush (stdout); - close (sock); - return 0; - } - if (pid < 0) { - fprintf (stderr, "Error: fork() failed: %s\n", - strerror (errno)); - close (sock); - return 1; - } - /* Reached if pid == 0 (the child process). */ - /* Close stdout so that the one interested in pid value will - also get EOF. */ - close (STDOUT_FILENO); - /* dup2() will re-reserve fd of stdout (1) (opportunistically), - in case fd of stderr (2) is open. If that was not open we - don't care fd of stdout (1) either. */ - dup2 (STDERR_FILENO, STDOUT_FILENO); + err = listen (sock, 1); + if (err) { + fprintf (stderr, "Error: listen() failed: %s\n", + strerror (errno)); + close (sock); + ret = 1; + goto DONE; + } - /* This process is now out of reach of shell's job control. - To resolve the rare but possible condition where this - "daemon" is started but never connected this process will - (only) have 30 seconds to exist. */ - alarm (30); + if (background) { + int pid = fork (); + if (pid > 0) { + printf ("smtp_dummy_pid='%d'\n", pid); + fflush (stdout); + close (sock); + ret = 0; + goto DONE; } - - peer_addr_len = sizeof (peer_addr); - peer = accept (sock, (struct sockaddr *) &peer_addr, &peer_addr_len); - if (peer == -1) { - fprintf (stderr, "Error: accept() failed: %s\n", - strerror (errno)); - return 1; + if (pid < 0) { + fprintf (stderr, "Error: fork() failed: %s\n", + strerror (errno)); + close (sock); + ret = 1; + goto DONE; } + /* Reached if pid == 0 (the child process). */ + /* Close stdout so that the one interested in pid value will + * also get EOF. */ + close (STDOUT_FILENO); + /* dup2() will re-reserve fd of stdout (1) (opportunistically), + * in case fd of stderr (2) is open. If that was not open we + * don't care fd of stdout (1) either. */ + dup2 (STDERR_FILENO, STDOUT_FILENO); - peer_file = fdopen (peer, "w+"); - if (peer_file == NULL) { - fprintf (stderr, "Error: fdopen() failed: %s\n", - strerror (errno)); - return 1; - } + /* This process is now out of reach of shell's job control. + * To resolve the rare but possible condition where this + * "daemon" is started but never connected this process will + * (only) have 30 seconds to exist. */ + alarm (30); + } + + peer_addr_len = sizeof (peer_addr); + peer = accept (sock, (struct sockaddr *) &peer_addr, &peer_addr_len); + if (peer == -1) { + fprintf (stderr, "Error: accept() failed: %s\n", + strerror (errno)); + ret = 1; + goto DONE; + } + + peer_file = fdopen (peer, "w+"); + if (peer_file == NULL) { + fprintf (stderr, "Error: fdopen() failed: %s\n", + strerror (errno)); + ret = 1; + goto DONE; + } - do_smtp_to_file (peer_file, output); + do_smtp_to_file (peer_file, output); + DONE: + if (output) fclose (output); + if (peer_file) fclose (peer_file); + if (sock >= 0) close (sock); - return 0; + return ret; } diff --git a/test/test-databases/.gitignore b/test/test-databases/.gitignore index b5624b74..9452199f 100644 --- a/test/test-databases/.gitignore +++ b/test/test-databases/.gitignore @@ -1 +1 @@ -*.tar.xz +/*.tar.xz diff --git a/test/test-lib-common.sh b/test/test-lib-common.sh index ef409171..2f7950ac 100644 --- a/test/test-lib-common.sh +++ b/test/test-lib-common.sh @@ -24,53 +24,213 @@ # type die >/dev/null 2>&1 || die () { echo "$@" >&2; exit 1; } -find_notmuch_path () -{ - dir="$1" - - while [ -n "$dir" ]; do - bin="$dir/notmuch" - if [ -x "$bin" ]; then - echo "$dir" - return - fi - dir="$(dirname "$dir")" - if [ "$dir" = "/" ]; then - break - fi - done -} +if [[ -z "$NOTMUCH_SRCDIR" ]] || [[ -z "$NOTMUCH_BUILDDIR" ]]; then + echo "internal: srcdir or builddir not set" >&2 + exit 1 +fi backup_database () { test_name=$(basename $0 .sh) - rm -rf notmuch-dir-backup."$test_name" - cp -pR ${MAIL_DIR}/.notmuch notmuch-dir-backup."${test_name}" + rm -rf $TMP_DIRECTORY/notmuch-dir-backup."$test_name" + cp -pR ${MAIL_DIR}/.notmuch $TMP_DIRECTORY/notmuch-dir-backup."${test_name}" } restore_database () { test_name=$(basename $0 .sh) rm -rf ${MAIL_DIR}/.notmuch - cp -pR notmuch-dir-backup."${test_name}" ${MAIL_DIR}/.notmuch + cp -pR $TMP_DIRECTORY/notmuch-dir-backup."${test_name}" ${MAIL_DIR}/.notmuch } -# Test the binaries we have just built. The tests are kept in -# test/ subdirectory and are run in 'trash directory' subdirectory. -TEST_DIRECTORY=$(pwd -P) -notmuch_path=`find_notmuch_path "$TEST_DIRECTORY"` - # Prepend $TEST_DIRECTORY/../lib to LD_LIBRARY_PATH, to make tests work # on systems where ../notmuch depends on LD_LIBRARY_PATH. LD_LIBRARY_PATH=${TEST_DIRECTORY%/*}/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH} export LD_LIBRARY_PATH # configure output -. $notmuch_path/sh.config || exit 1 +. "$NOTMUCH_BUILDDIR/sh.config" || exit 1 # load OS specifics -if [ -e ./test-lib-$PLATFORM.sh ]; then - . ./test-lib-$PLATFORM.sh || exit 1 +if [[ -e "$NOTMUCH_SRCDIR/test/test-lib-$PLATFORM.sh" ]]; then + . "$NOTMUCH_SRCDIR/test/test-lib-$PLATFORM.sh" || exit 1 fi +# Generate a new message in the mail directory, with a unique message +# ID and subject. The message is not added to the index. +# +# After this function returns, the filename of the generated message +# is available as $gen_msg_filename and the message ID is available as +# $gen_msg_id . +# +# This function supports named parameters with the bash syntax for +# assigning a value to an associative array ([name]=value). The +# supported parameters are: +# +# [dir]=directory/of/choice +# +# Generate the message in directory 'directory/of/choice' within +# the mail store. The directory will be created if necessary. +# +# [filename]=name +# +# Store the message in file 'name'. The default is to store it +# in 'msg-<count>', where <count> is three-digit number of the +# message. +# +# [body]=text +# +# Text to use as the body of the email message +# +# '[from]="Some User <user@example.com>"' +# '[to]="Some User <user@example.com>"' +# '[subject]="Subject of email message"' +# '[date]="RFC 822 Date"' +# +# Values for email headers. If not provided, default values will +# be generated instead. +# +# '[cc]="Some User <user@example.com>"' +# [reply-to]=some-address +# [in-reply-to]=<message-id> +# [references]=<message-id> +# [content-type]=content-type-specification +# '[header]=full header line, including keyword' +# +# Additional values for email headers. If these are not provided +# then the relevant headers will simply not appear in the +# message. +# +# '[id]=message-id' +# +# Controls the message-id of the created message. +gen_msg_cnt=0 +gen_msg_filename="" +gen_msg_id="" +generate_message () +{ + # This is our (bash-specific) magic for doing named parameters + local -A template="($@)" + local additional_headers + + gen_msg_cnt=$((gen_msg_cnt + 1)) + if [ -z "${template[filename]}" ]; then + gen_msg_name="msg-$(printf "%03d" $gen_msg_cnt)" + else + gen_msg_name=${template[filename]} + fi + + if [ -z "${template[id]}" ]; then + gen_msg_id="${gen_msg_name%:2,*}@notmuch-test-suite" + else + gen_msg_id="${template[id]}" + fi + + if [ -z "${template[dir]}" ]; then + gen_msg_filename="${MAIL_DIR}/$gen_msg_name" + else + gen_msg_filename="${MAIL_DIR}/${template[dir]}/$gen_msg_name" + mkdir -p "$(dirname "$gen_msg_filename")" + fi + + if [ -z "${template[body]}" ]; then + template[body]="This is just a test message (#${gen_msg_cnt})" + fi + + if [ -z "${template[from]}" ]; then + template[from]="Notmuch Test Suite <test_suite@notmuchmail.org>" + fi + + if [ -z "${template[to]}" ]; then + template[to]="Notmuch Test Suite <test_suite@notmuchmail.org>" + fi + + if [ -z "${template[subject]}" ]; then + if [ -n "$test_subtest_name" ]; then + template[subject]="$test_subtest_name" + else + template[subject]="Test message #${gen_msg_cnt}" + fi + elif [ "${template[subject]}" = "@FORCE_EMPTY" ]; then + template[subject]="" + fi + + if [ -z "${template[date]}" ]; then + # we use decreasing timestamps here for historical reasons; + # the existing test suite when we converted to unique timestamps just + # happened to have signicantly fewer failures with that choice. + local date_secs=$((978709437 - gen_msg_cnt)) + # printf %(..)T is bash 4.2+ feature. use perl fallback if needed... + TZ=UTC printf -v template[date] "%(%a, %d %b %Y %T %z)T" $date_secs 2>/dev/null || + template[date]=`perl -le 'use POSIX "strftime"; + @time = gmtime '"$date_secs"'; + print strftime "%a, %d %b %Y %T +0000", @time'` + fi + + additional_headers="" + if [ ! -z "${template[header]}" ]; then + additional_headers="${template[header]} +${additional_headers}" + fi + + if [ ! -z "${template[reply-to]}" ]; then + additional_headers="Reply-To: ${template[reply-to]} +${additional_headers}" + fi + + if [ ! -z "${template[in-reply-to]}" ]; then + additional_headers="In-Reply-To: ${template[in-reply-to]} +${additional_headers}" + fi + + if [ ! -z "${template[cc]}" ]; then + additional_headers="Cc: ${template[cc]} +${additional_headers}" + fi + + if [ ! -z "${template[bcc]}" ]; then + additional_headers="Bcc: ${template[bcc]} +${additional_headers}" + fi + + if [ ! -z "${template[references]}" ]; then + additional_headers="References: ${template[references]} +${additional_headers}" + fi + + if [ ! -z "${template[content-type]}" ]; then + additional_headers="Content-Type: ${template[content-type]} +${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). + + cat <<EOF >"$gen_msg_filename" +From: ${template[from]} +To: ${template[to]} +Message-Id: <${gen_msg_id}> +Subject: ${template[subject]} +Date: ${template[date]} +${additional_headers} +${template[body]} +EOF +} + +# Generate a new message and add it to the database. +# +# All of the arguments and return values supported by generate_message +# are also supported here, so see that function for details. +add_message () +{ + generate_message "$@" && + notmuch new > /dev/null +} + if test -n "$valgrind" then make_symlink () { @@ -131,25 +291,21 @@ then PATH=$GIT_VALGRIND/bin:$PATH GIT_EXEC_PATH=$GIT_VALGRIND/bin export GIT_VALGRIND - test -n "$notmuch_path" && MANPATH="$notmuch_path/doc/_build/man" + test -n "$NOTMUCH_BUILDDIR" && MANPATH="$NOTMUCH_BUILDDIR/doc/_build/man" else # normal case - if test -n "$notmuch_path" + if test -n "$NOTMUCH_BUILDDIR" then - PATH="$notmuch_path:$PATH" - MANPATH="$notmuch_path/doc/_build/man" + PATH="$NOTMUCH_BUILDDIR:$PATH" + MANPATH="$NOTMUCH_BUILDDIR/doc/_build/man" fi fi export PATH MANPATH # Test repository test="tmp.$(basename "$0" .sh)" -test -n "$root" && test="$root/$test" -case "$test" in -/*) TMP_DIRECTORY="$test" ;; - *) TMP_DIRECTORY="$TEST_DIRECTORY/$test" ;; -esac +TMP_DIRECTORY="$TEST_DIRECTORY/$test" test ! -z "$debug" || remove_tmp=$TMP_DIRECTORY -rm -fr "$test" || { +rm -rf "$TMP_DIRECTORY" || { GIT_EXIT_OK=t echo >&6 "FATAL: Cannot prepare test area" exit 1 @@ -165,7 +321,6 @@ mkdir -p "${HOME}" MAIL_DIR="${TMP_DIRECTORY}/mail" export NOTMUCH_CONFIG="${TMP_DIRECTORY}/notmuch-config" -mkdir -p "${test}" mkdir -p "${MAIL_DIR}" cat <<EOF >"${NOTMUCH_CONFIG}" diff --git a/test/test-lib.sh b/test/test-lib.sh index 7ae96c69..5b212514 100644 --- a/test/test-lib.sh +++ b/test/test-lib.sh @@ -26,6 +26,15 @@ fi # Make sure echo builtin does not expand backslash-escape sequences by default. shopt -u xpg_echo +# Ensure NOTMUCH_SRCDIR and NOTMUCH_BUILDDIR are set. +. $(dirname "$0")/export-dirs.sh || exit 1 + +# It appears that people try to run tests without building... +if [[ ! -x "$NOTMUCH_BUILDDIR/notmuch" ]]; then + echo >&2 'You do not seem to have built notmuch yet.' + exit 1 +fi + this_test=${0##*/} this_test=${this_test%.sh} this_test_bare=${this_test#T[0-9][0-9][0-9]-} @@ -93,6 +102,23 @@ unset GREP_OPTIONS # For emacsclient unset ALTERNATE_EDITOR +add_gnupg_home () +{ + local output + [ -d ${GNUPGHOME} ] && return + _gnupg_exit () { gpgconf --kill all 2>/dev/null || true; } + at_exit_function _gnupg_exit + mkdir -m 0700 "$GNUPGHOME" + gpg --no-tty --import <$NOTMUCH_SRCDIR/test/gnupg-secret-key.asc >"$GNUPGHOME"/import.log 2>&1 + test_debug "cat $GNUPGHOME/import.log" + if (gpg --quick-random --version >/dev/null 2>&1) ; then + echo quick-random >> "$GNUPGHOME"/gpg.conf + elif (gpg --debug-quick-random --version >/dev/null 2>&1) ; then + echo debug-quick-random >> "$GNUPGHOME"/gpg.conf + fi + echo no-emit-version >> "$GNUPGHOME"/gpg.conf +} + # Each test should start with something like this, after copyright notices: # # test_description='Description of this test... @@ -134,9 +160,6 @@ do valgrind=t; verbose=t; shift ;; --tee) shift ;; # was handled already - --root=*) - root=$(expr "z$1" : 'z[^=]*=\(.*\)') - shift ;; *) echo "error: unknown test option '$1'" >&2; exit 1 ;; esac @@ -276,183 +299,6 @@ export GNUPGHOME="${TEST_TMPDIR}/gnupg" trap 'trap_exit' EXIT trap 'trap_signal' HUP INT TERM -# Generate a new message in the mail directory, with a unique message -# ID and subject. The message is not added to the index. -# -# After this function returns, the filename of the generated message -# is available as $gen_msg_filename and the message ID is available as -# $gen_msg_id . -# -# This function supports named parameters with the bash syntax for -# assigning a value to an associative array ([name]=value). The -# supported parameters are: -# -# [dir]=directory/of/choice -# -# Generate the message in directory 'directory/of/choice' within -# the mail store. The directory will be created if necessary. -# -# [filename]=name -# -# Store the message in file 'name'. The default is to store it -# in 'msg-<count>', where <count> is three-digit number of the -# message. -# -# [body]=text -# -# Text to use as the body of the email message -# -# '[from]="Some User <user@example.com>"' -# '[to]="Some User <user@example.com>"' -# '[subject]="Subject of email message"' -# '[date]="RFC 822 Date"' -# -# Values for email headers. If not provided, default values will -# be generated instead. -# -# '[cc]="Some User <user@example.com>"' -# [reply-to]=some-address -# [in-reply-to]=<message-id> -# [references]=<message-id> -# [content-type]=content-type-specification -# '[header]=full header line, including keyword' -# -# Additional values for email headers. If these are not provided -# then the relevant headers will simply not appear in the -# message. -# -# '[id]=message-id' -# -# Controls the message-id of the created message. -gen_msg_cnt=0 -gen_msg_filename="" -gen_msg_id="" -generate_message () -{ - # This is our (bash-specific) magic for doing named parameters - local -A template="($@)" - local additional_headers - - gen_msg_cnt=$((gen_msg_cnt + 1)) - if [ -z "${template[filename]}" ]; then - gen_msg_name="msg-$(printf "%03d" $gen_msg_cnt)" - else - gen_msg_name=${template[filename]} - fi - - if [ -z "${template[id]}" ]; then - gen_msg_id="${gen_msg_name%:2,*}@notmuch-test-suite" - else - gen_msg_id="${template[id]}" - fi - - if [ -z "${template[dir]}" ]; then - gen_msg_filename="${MAIL_DIR}/$gen_msg_name" - else - gen_msg_filename="${MAIL_DIR}/${template[dir]}/$gen_msg_name" - mkdir -p "$(dirname "$gen_msg_filename")" - fi - - if [ -z "${template[body]}" ]; then - template[body]="This is just a test message (#${gen_msg_cnt})" - fi - - if [ -z "${template[from]}" ]; then - template[from]="Notmuch Test Suite <test_suite@notmuchmail.org>" - fi - - if [ -z "${template[to]}" ]; then - template[to]="Notmuch Test Suite <test_suite@notmuchmail.org>" - fi - - if [ -z "${template[subject]}" ]; then - if [ -n "$test_subtest_name" ]; then - template[subject]="$test_subtest_name" - else - template[subject]="Test message #${gen_msg_cnt}" - fi - elif [ "${template[subject]}" = "@FORCE_EMPTY" ]; then - template[subject]="" - fi - - if [ -z "${template[date]}" ]; then - # we use decreasing timestamps here for historical reasons; - # the existing test suite when we converted to unique timestamps just - # happened to have signicantly fewer failures with that choice. - local date_secs=$((978709437 - gen_msg_cnt)) - # printf %(..)T is bash 4.2+ feature. use perl fallback if needed... - TZ=UTC printf -v template[date] "%(%a, %d %b %Y %T %z)T" $date_secs 2>/dev/null || - template[date]=`perl -le 'use POSIX "strftime"; - @time = gmtime '"$date_secs"'; - print strftime "%a, %d %b %Y %T +0000", @time'` - fi - - additional_headers="" - if [ ! -z "${template[header]}" ]; then - additional_headers="${template[header]} -${additional_headers}" - fi - - if [ ! -z "${template[reply-to]}" ]; then - additional_headers="Reply-To: ${template[reply-to]} -${additional_headers}" - fi - - if [ ! -z "${template[in-reply-to]}" ]; then - additional_headers="In-Reply-To: ${template[in-reply-to]} -${additional_headers}" - fi - - if [ ! -z "${template[cc]}" ]; then - additional_headers="Cc: ${template[cc]} -${additional_headers}" - fi - - if [ ! -z "${template[bcc]}" ]; then - additional_headers="Bcc: ${template[bcc]} -${additional_headers}" - fi - - if [ ! -z "${template[references]}" ]; then - additional_headers="References: ${template[references]} -${additional_headers}" - fi - - if [ ! -z "${template[content-type]}" ]; then - additional_headers="Content-Type: ${template[content-type]} -${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). - - cat <<EOF >"$gen_msg_filename" -From: ${template[from]} -To: ${template[to]} -Message-Id: <${gen_msg_id}> -Subject: ${template[subject]} -Date: ${template[date]} -${additional_headers} -${template[body]} -EOF -} - -# Generate a new message and add it to the database. -# -# All of the arguments and return values supported by generate_message -# are also supported here, so see that function for details. -add_message () -{ - generate_message "$@" && - notmuch new > /dev/null -} - # Deliver a message with emacs and add it to the database # # Uses emacs to generate and deliver a message to the mail store. @@ -500,8 +346,17 @@ emacs_deliver_message () # Accepts arbitrary extra emacs/elisp functions to modify the message # before sending, which is useful to doing things like attaching files # to the message and encrypting/signing. +# +# If any GNU-style long-arguments (like --quiet or --decrypt=true) are +# at the head of the argument list, they are sent directly to "notmuch +# new" after message delivery emacs_fcc_message () { + local nmn_args='' + while [[ "$1" =~ ^-- ]]; do + nmn_args="$nmn_args $1" + shift + done local subject="$1" local body="$2" shift 2 @@ -520,7 +375,7 @@ emacs_fcc_message () (insert \"${body}\") $@ (notmuch-mua-send-and-exit))" || return 1 - notmuch new >/dev/null + notmuch new $nmn_args >/dev/null } # Add an existing, fixed corpus of email to the database. @@ -539,7 +394,7 @@ add_email_corpus () if [ -d $TEST_DIRECTORY/corpora.mail/$corpus ]; then cp -a $TEST_DIRECTORY/corpora.mail/$corpus ${MAIL_DIR} else - cp -a $TEST_DIRECTORY/corpora/$corpus ${MAIL_DIR} + cp -a $NOTMUCH_SRCDIR/test/corpora/$corpus ${MAIL_DIR} notmuch new >/dev/null || die "'notmuch new' failed while adding email corpus" mkdir -p $TEST_DIRECTORY/corpora.mail cp -a ${MAIL_DIR} $TEST_DIRECTORY/corpora.mail/$corpus @@ -627,9 +482,10 @@ test_expect_equal_json () { # The test suite forces LC_ALL=C, but this causes Python 3 to # decode stdin as ASCII. We need to read JSON in UTF-8, so # override Python's stdio encoding defaults. - output=$(echo "$1" | PYTHONIOENCODING=utf-8 $NOTMUCH_PYTHON -mjson.tool \ + local script='import json, sys; json.dump(json.load(sys.stdin), sys.stdout, sort_keys=True, indent=4)' + output=$(echo "$1" | PYTHONIOENCODING=utf-8 $NOTMUCH_PYTHON -c "$script" \ || echo "$1") - expected=$(echo "$2" | PYTHONIOENCODING=utf-8 $NOTMUCH_PYTHON -mjson.tool \ + expected=$(echo "$2" | PYTHONIOENCODING=utf-8 $NOTMUCH_PYTHON -c "$script" \ || echo "$2") shift 2 test_expect_equal "$output" "$expected" "$@" @@ -683,6 +539,16 @@ NOTMUCH_DUMP_TAGS () notmuch dump --include=tags "${@}" | sed '/^#/d' | sort } +notmuch_drop_mail_headers () +{ + $NOTMUCH_PYTHON -c ' +import email, sys +msg = email.message_from_file(sys.stdin) +for hdr in sys.argv[1:]: del msg[hdr] +print(msg.as_string(False)) +' "$@" +} + notmuch_search_sanitize () { perl -pe 's/("?thread"?: ?)("?)................("?)/\1\2XXX\3/' @@ -1077,8 +943,8 @@ export NOTMUCH_CONFIG=$NOTMUCH_CONFIG # --load Force loading of notmuch.el and test-lib.el exec ${TEST_EMACS} --quick \ - --directory "$TEST_DIRECTORY/../emacs" --load notmuch.el \ - --directory "$TEST_DIRECTORY" --load test-lib.el \ + --directory "$NOTMUCH_SRCDIR/emacs" --load notmuch.el \ + --directory "$NOTMUCH_SRCDIR/test" --load test-lib.el \ "\$@" EOF chmod a+x "$TMP_DIRECTORY/run_emacs" @@ -1093,8 +959,8 @@ test_emacs () { test -z "$missing_dependencies" || return if [ -z "$EMACS_SERVER" ]; then - emacs_tests="${this_test_bare}.el" - if [ -f "$TEST_DIRECTORY/$emacs_tests" ]; then + emacs_tests="$NOTMUCH_SRCDIR/test/${this_test_bare}.el" + if [ -f "$emacs_tests" ]; then load_emacs_tests="--eval '(load \"$emacs_tests\")'" else load_emacs_tests= @@ -1137,14 +1003,14 @@ test_python() { } test_ruby() { - MAIL_DIR=$MAIL_DIR ruby -I $TEST_DIRECTORY/../bindings/ruby> OUTPUT + MAIL_DIR=$MAIL_DIR ruby -I $NOTMUCH_SRCDIR/bindings/ruby> OUTPUT } test_C () { exec_file="test${test_count}" test_file="${exec_file}.c" cat > ${test_file} - ${TEST_CC} ${TEST_CFLAGS} -I${TEST_DIRECTORY} -I${NOTMUCH_SRCDIR}/lib -o ${exec_file} ${test_file} -L${TEST_DIRECTORY}/../lib/ -lnotmuch -ltalloc + ${TEST_CC} ${TEST_CFLAGS} -I${NOTMUCH_SRCDIR}/test -I${NOTMUCH_SRCDIR}/lib -o ${exec_file} ${test_file} -L${NOTMUCH_BUILDDIR}/lib/ -lnotmuch -ltalloc echo "== stdout ==" > OUTPUT.stdout echo "== stderr ==" > OUTPUT.stderr ./${exec_file} "$@" 1>>OUTPUT.stdout 2>>OUTPUT.stderr @@ -1200,7 +1066,10 @@ test_init_ () { } -. ./test-lib-common.sh || exit 1 +# Where to run the tests +TEST_DIRECTORY=$NOTMUCH_BUILDDIR/test + +. "$NOTMUCH_SRCDIR/test/test-lib-common.sh" || exit 1 if [ "${NOTMUCH_GMIME_MAJOR}" = 3 ]; then test_subtest_broken_gmime_3 () { @@ -1223,7 +1092,7 @@ emacs_generate_script # Use -P to resolve symlinks in our working directory so that the cwd # in subprocesses like git equals our $PWD (for pathname comparisons). -cd -P "$test" || error "Cannot set up test environment" +cd -P "$TMP_DIRECTORY" || error "Cannot set up test environment" if test "$verbose" = "t" then diff --git a/test/test-verbose b/test/test-verbose index 158be28a..8af6d9a9 100755 --- a/test/test-verbose +++ b/test/test-verbose @@ -2,7 +2,7 @@ test_description='the verbosity options of the test framework itself.' -. ./test-lib.sh || exit 1 +. $(dirname "$0")/test-lib.sh || exit 1 test_begin_subtest 'print something in test_expect_success and pass' test_expect_success ' |
