complete ghost-on-removal-when-shared-thread-exists
[notmuch] / test / T590-thread-breakage.sh
1 #!/usr/bin/env bash
2 #
3 # Copyright (c) 2016 Daniel Kahn Gillmor
4 #
5
6 test_description='thread breakage during reindexing
7
8 notmuch uses ghost documents to track messages we have seen references
9 to but have never seen.  Regardless of the order of delivery, message
10 deletion, and reindexing, the list of ghost messages for a given
11 stored corpus should not vary, so that threads can be reassmebled
12 cleanly.
13
14 In practice, we accept a small amount of variation (and therefore
15 traffic pattern metadata leakage to be stored in the index) for the
16 sake of efficiency.
17
18 This test also embeds some subtests to ensure that indexing actually
19 works properly and attempted fixes to threading issues do not break
20 the expected contents of the index.'
21
22 . ./test-lib.sh || exit 1
23
24 message_a() {
25     mkdir -p ${MAIL_DIR}/cur
26     cat > ${MAIL_DIR}/cur/a <<EOF
27 Subject: First message
28 Message-ID: <a@example.net>
29 From: Alice <alice@example.net>
30 To: Bob <bob@example.net>
31 Date: Thu, 31 Mar 2016 20:10:00 -0400
32
33 This is the first message in the thread.
34 Apple
35 EOF
36 }
37
38 message_b() {
39     mkdir -p ${MAIL_DIR}/cur
40     cat > ${MAIL_DIR}/cur/b <<EOF
41 Subject: Second message
42 Message-ID: <b@example.net>
43 In-Reply-To: <a@example.net>
44 References: <a@example.net>
45 From: Bob <bob@example.net>
46 To: Alice <alice@example.net>
47 Date: Thu, 31 Mar 2016 20:15:00 -0400
48
49 This is the second message in the thread.
50 Banana
51 EOF
52 }
53
54
55 test_content_count() {
56     test_begin_subtest "${3:-looking for $2 instance of '$1'}"
57     count=$(notmuch count --output=threads "$1")
58     test_expect_equal "$count" "$2"
59 }
60
61 test_thread_count() {
62     test_begin_subtest "${2:-Expecting $1 thread(s)}"
63     count=$(notmuch count --output=threads)
64     test_expect_equal "$count" "$1"
65 }
66
67 test_ghost_count() {
68     test_begin_subtest "${2:-Expecting $1 ghosts(s)}"
69     ghosts=$(../ghost-report ${MAIL_DIR}/.notmuch/xapian)
70     test_expect_equal "$ghosts" "$1"
71 }
72
73 notmuch new >/dev/null
74
75 test_thread_count 0 'There should be no threads initially'
76 test_ghost_count 0 'There should be no ghosts initially'
77
78 message_a
79 notmuch new >/dev/null
80 test_thread_count 1 'One message in: one thread'
81 test_content_count apple 1
82 test_content_count banana 0
83 test_ghost_count 0
84
85 message_b
86 notmuch new >/dev/null
87 test_thread_count 1 'Second message in the same thread: one thread'
88 test_content_count apple 1
89 test_content_count banana 1
90 test_ghost_count 0
91
92 rm -f ${MAIL_DIR}/cur/a
93 notmuch new >/dev/null
94 test_thread_count 1 'First message removed: still only one thread'
95 test_content_count apple 0
96 test_content_count banana 1
97 test_ghost_count 1 'should be one ghost after first message removed'
98
99 message_a
100 notmuch new >/dev/null
101 test_thread_count 1 'First message reappears: should return to the same thread'
102 test_content_count apple 1
103 test_content_count banana 1
104 test_ghost_count 0
105
106 rm -f ${MAIL_DIR}/cur/b
107 notmuch new >/dev/null
108 test_thread_count 1 'Removing second message: still only one thread'
109 test_content_count apple 1
110 test_content_count banana 0
111 test_begin_subtest 'No ghosts should remain after deletion of second message'
112 # this is known to fail; we are leaking ghost messages deliberately
113 test_subtest_known_broken
114 ghosts=$(../ghost-report ${MAIL_DIR}/.notmuch/xapian)
115 test_expect_equal "$ghosts" "0"
116
117 rm -f ${MAIL_DIR}/cur/a
118 notmuch new >/dev/null
119 test_thread_count 0 'All messages gone: no threads'
120 test_content_count apple 0
121 test_content_count banana 0
122 test_ghost_count 0 'No ghosts should remain after full thread deletion'
123
124 test_done