]> git.notmuchmail.org Git - notmuch/blob - test/T610-message-property.sh
lib/database: delete stemmer on destroy
[notmuch] / test / T610-message-property.sh
1 #!/usr/bin/env bash
2 test_description="message property API"
3
4 . $(dirname "$0")/test-lib.sh || exit 1
5
6 add_email_corpus
7
8 cat <<EOF > c_head
9 #include <notmuch-test.h>
10
11 void print_properties (notmuch_message_t *message, const char *prefix, notmuch_bool_t exact) {
12     notmuch_message_properties_t *list;
13     for (list = notmuch_message_get_properties (message, prefix, exact);
14          notmuch_message_properties_valid (list); notmuch_message_properties_move_to_next (list)) {
15        printf("%s\n", notmuch_message_properties_value(list));
16     }
17     notmuch_message_properties_destroy (list);
18 }
19
20 int main (int argc, char** argv)
21 {
22    notmuch_database_t *db;
23    notmuch_message_t *message = NULL;
24    const char *val;
25    notmuch_status_t stat;
26
27    EXPECT0(notmuch_database_open (argv[1], NOTMUCH_DATABASE_MODE_READ_WRITE, &db));
28    EXPECT0(notmuch_database_find_message(db, "4EFC743A.3060609@april.org", &message));
29    if (message == NULL) {
30         fprintf (stderr, "unable to find message");
31         exit (1);
32    }
33 EOF
34
35 cat <<EOF > c_tail
36    EXPECT0(notmuch_database_destroy(db));
37 }
38 EOF
39
40 test_begin_subtest "notmuch_message_{add,get,remove}_property"
41 cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR}
42 {
43    EXPECT0(notmuch_message_add_property (message, "testkey1", "testvalue1"));
44    EXPECT0(notmuch_message_get_property (message, "testkey1", &val));
45    printf("testkey1[1] = %s\n", val);
46    EXPECT0(notmuch_message_add_property (message, "testkey2", "this value has spaces and = sign"));
47    EXPECT0(notmuch_message_get_property (message, "testkey1", &val));
48    printf("testkey1[2] = %s\n", val);
49    EXPECT0(notmuch_message_get_property (message, "testkey1", &val));
50
51    EXPECT0(notmuch_message_get_property (message, "testkey2", &val));
52    printf("testkey2 = %s\n", val);
53
54    /* Add second value for key */
55    EXPECT0(notmuch_message_add_property (message, "testkey2", "zztestvalue3"));
56    EXPECT0(notmuch_message_get_property (message, "testkey2", &val));
57    printf("testkey2 = %s\n", val);
58
59    /* remove first value for key */
60    EXPECT0(notmuch_message_remove_property (message, "testkey2", "this value has spaces and = sign"));
61    EXPECT0(notmuch_message_get_property (message, "testkey2", &val));
62    printf("testkey2 = %s\n", val);
63
64    /* remove non-existent value for key */
65    EXPECT0(notmuch_message_remove_property (message, "testkey2", "this value has spaces and = sign"));
66    EXPECT0(notmuch_message_get_property (message, "testkey2", &val));
67    printf("testkey2 = %s\n", val);
68
69    /* remove only value for key */
70    EXPECT0(notmuch_message_remove_property (message, "testkey2", "zztestvalue3"));
71    EXPECT0(notmuch_message_get_property (message, "testkey2", &val));
72    printf("testkey2 = %s\n", val == NULL ? "NULL" : val);
73 }
74 EOF
75 cat <<'EOF' >EXPECTED
76 == stdout ==
77 testkey1[1] = testvalue1
78 testkey1[2] = testvalue1
79 testkey2 = this value has spaces and = sign
80 testkey2 = this value has spaces and = sign
81 testkey2 = zztestvalue3
82 testkey2 = zztestvalue3
83 testkey2 = NULL
84 == stderr ==
85 EOF
86 test_expect_equal_file EXPECTED OUTPUT
87
88 test_begin_subtest "notmuch_message_remove_all_properties"
89 cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR}
90 EXPECT0(notmuch_message_remove_all_properties (message, NULL));
91 print_properties (message, "", FALSE);
92 EOF
93 cat <<'EOF' >EXPECTED
94 == stdout ==
95 == stderr ==
96 EOF
97 test_expect_equal_file EXPECTED OUTPUT
98
99 test_begin_subtest "testing string map binary search (via message properties)"
100 cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR}
101 {
102    char *keys[] = {"a", "b", "c", "d", "e", NULL};
103    for (int i=0; keys[i]; i++)
104        EXPECT0(notmuch_message_add_property (message, keys[i], keys[i]));
105
106    for (int i=0; keys[i]; i++) {
107       EXPECT0(notmuch_message_get_property (message, keys[i], &val));
108       printf("%s = %s\n", keys[i], val);
109    }
110
111    for (int i=0; keys[i]; i++) {
112       EXPECT0(notmuch_message_remove_property (message, keys[i], keys[i]));
113       EXPECT0(notmuch_message_get_property (message, keys[i], &val));
114       printf("%s = %s\n", keys[i], val == NULL ? "NULL" : val);
115    }
116 }
117 EOF
118 cat <<EOF > EXPECTED
119 == stdout ==
120 a = a
121 b = b
122 c = c
123 d = d
124 e = e
125 a = NULL
126 b = NULL
127 c = NULL
128 d = NULL
129 e = NULL
130 == stderr ==
131 EOF
132 test_expect_equal_file EXPECTED OUTPUT
133
134 test_begin_subtest "notmuch_message_get_properties: empty list"
135 cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR}
136 {
137    notmuch_message_properties_t *list;
138    list = notmuch_message_get_properties (message, "nonexistent", TRUE);
139    printf("valid = %d\n", notmuch_message_properties_valid (list));
140    notmuch_message_properties_destroy (list);
141 }
142 EOF
143 cat <<'EOF' >EXPECTED
144 == stdout ==
145 valid = 0
146 == stderr ==
147 EOF
148 test_expect_equal_file EXPECTED OUTPUT
149
150 test_begin_subtest "notmuch_message_properties: one value"
151 cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR}
152 print_properties (message, "testkey1", TRUE);
153 EOF
154 cat <<'EOF' >EXPECTED
155 == stdout ==
156 testvalue1
157 == stderr ==
158 EOF
159 test_expect_equal_file EXPECTED OUTPUT
160
161 test_begin_subtest "notmuch_message_properties: multiple values"
162 cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR}
163 EXPECT0(notmuch_message_add_property (message, "testkey1", "bob"));
164 EXPECT0(notmuch_message_add_property (message, "testkey1", "testvalue2"));
165 EXPECT0(notmuch_message_add_property (message, "testkey1", "alice"));
166 print_properties (message, "testkey1", TRUE);
167 EOF
168 cat <<'EOF' >EXPECTED
169 == stdout ==
170 alice
171 bob
172 testvalue1
173 testvalue2
174 == stderr ==
175 EOF
176 test_expect_equal_file EXPECTED OUTPUT
177
178 test_begin_subtest "notmuch_message_properties: prefix"
179 cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR}
180 EXPECT0(notmuch_message_add_property (message, "testkey3", "bob3"));
181 EXPECT0(notmuch_message_add_property (message, "testkey3", "testvalue3"));
182 EXPECT0(notmuch_message_add_property (message, "testkey3", "alice3"));
183 print_properties (message, "testkey", FALSE);
184 EOF
185 # expected: 4 values for testkey1, 3 values for testkey3
186 # they are not guaranteed to be sorted, so sort them, leaving the first
187 # line '== stdout ==' and the end ('== stderr ==' and whatever error
188 # may have been printed) alone
189 mv OUTPUT unsorted_OUTPUT
190 awk ' NR == 1 { print; next } \
191       NR < 6  { print | "sort"; next } \
192       NR == 6 { close("sort") } \
193       NR < 9  { print | "sort"; next } \
194       NR == 9 { close("sort") } \
195       { print }' unsorted_OUTPUT > OUTPUT
196 rm unsorted_OUTPUT
197 cat <<'EOF' >EXPECTED
198 == stdout ==
199 alice
200 bob
201 testvalue1
202 testvalue2
203 alice3
204 bob3
205 testvalue3
206 == stderr ==
207 EOF
208 test_expect_equal_file EXPECTED OUTPUT
209
210 test_begin_subtest "notmuch_message_properties: modify during iteration"
211 cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR}
212 {
213     const char *keys[1000] = {NULL};
214     const char *vals[1000] = {NULL};
215     notmuch_message_properties_t *properties;
216     int i;
217
218     for (properties = notmuch_message_get_properties (message, "", FALSE), i=0;
219          notmuch_message_properties_valid (properties);
220          notmuch_message_properties_move_to_next (properties), i++)
221     {
222         const char *key, *value;
223
224         keys[i]=talloc_strdup(message,
225                     notmuch_message_properties_key (properties));
226         vals[i]=talloc_strdup(message,
227                     notmuch_message_properties_value (properties));
228
229         EXPECT0(notmuch_message_remove_property (message, keys[i], vals[i]));
230     }
231
232     print_properties (message, "", FALSE);
233
234     for (i = 0; keys[i] && vals[i]; i++) {
235         EXPECT0(notmuch_message_add_property (message, keys[i], vals[i]));
236     }
237 }
238 EOF
239 cat <<'EOF' >EXPECTED
240 == stdout ==
241 == stderr ==
242 EOF
243 test_expect_equal_file EXPECTED OUTPUT
244
245 test_begin_subtest "dump message properties"
246 cat <<EOF > PROPERTIES
247 #= 4EFC743A.3060609@april.org fancy%20key%20with%20%c3%a1cc%c3%a8nts=import%20value%20with%20= testkey1=alice testkey1=bob testkey1=testvalue1 testkey1=testvalue2 testkey3=alice3 testkey3=bob3 testkey3=testvalue3
248 EOF
249 cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR}
250 EXPECT0(notmuch_message_add_property (message, "fancy key with áccènts", "import value with ="));
251 EOF
252 notmuch dump | grep '^#=' > OUTPUT
253 test_expect_equal_file PROPERTIES OUTPUT
254
255 test_begin_subtest "dump _only_ message properties"
256 cat <<EOF > EXPECTED
257 #notmuch-dump batch-tag:3 properties
258 #= 4EFC743A.3060609@april.org fancy%20key%20with%20%c3%a1cc%c3%a8nts=import%20value%20with%20= testkey1=alice testkey1=bob testkey1=testvalue1 testkey1=testvalue2 testkey3=alice3 testkey3=bob3 testkey3=testvalue3
259 EOF
260 notmuch dump --include=properties > OUTPUT
261 test_expect_equal_file EXPECTED OUTPUT
262
263
264 test_begin_subtest "restore missing message property (single line)"
265 notmuch dump | grep '^#=' > BEFORE1
266 cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR}
267 EXPECT0(notmuch_message_remove_property (message, "testkey1", "bob"));
268 EOF
269 notmuch restore < BEFORE1
270 notmuch dump | grep '^#=' > OUTPUT
271 test_expect_equal_file PROPERTIES OUTPUT
272
273
274 test_begin_subtest "restore missing message property (full dump)"
275 notmuch dump > BEFORE2
276 cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR}
277 EXPECT0(notmuch_message_remove_property (message, "testkey1", "bob"));
278 EOF
279 notmuch restore < BEFORE2
280 notmuch dump | grep '^#=' > OUTPUT
281 test_expect_equal_file PROPERTIES OUTPUT
282
283 test_begin_subtest "restore clear extra message property"
284 cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR}
285 EXPECT0(notmuch_message_add_property (message, "testkey1", "charles"));
286 EOF
287 notmuch restore < BEFORE2
288 notmuch dump | grep '^#=' > OUTPUT
289 test_expect_equal_file PROPERTIES OUTPUT
290
291 test_begin_subtest "test 'property:' queries: empty"
292 notmuch search property:testkey1=charles > OUTPUT
293 test_expect_equal_file /dev/null OUTPUT
294
295 test_begin_subtest "test 'property:' queries: single message"
296 notmuch search --output=messages property:testkey1=alice > OUTPUT
297 cat <<EOF >EXPECTED
298 id:4EFC743A.3060609@april.org
299 EOF
300 test_expect_equal_file EXPECTED OUTPUT
301
302 test_begin_subtest "msg.get_property (python)"
303 test_python <<'EOF'
304 import notmuch
305 db = notmuch.Database(mode=notmuch.Database.MODE.READ_WRITE)
306 msg = db.find_message("4EFC743A.3060609@april.org")
307 print("testkey1 = {0}".format(msg.get_property("testkey1")))
308 print("testkey3 = {0}".format(msg.get_property("testkey3")))
309 EOF
310 cat <<'EOF' > EXPECTED
311 testkey1 = alice
312 testkey3 = alice3
313 EOF
314 test_expect_equal_file EXPECTED OUTPUT
315
316 test_begin_subtest "msg.get_properties (python)"
317 test_python <<'EOF'
318 import notmuch
319 db = notmuch.Database(mode=notmuch.Database.MODE.READ_ONLY)
320 msg = db.find_message("4EFC743A.3060609@april.org")
321 for (key,val) in msg.get_properties("testkey1"):
322         print("{0} = {1}".format(key,val))
323 EOF
324 cat <<'EOF' > EXPECTED
325 testkey1 = alice
326 testkey1 = bob
327 testkey1 = testvalue1
328 testkey1 = testvalue2
329 EOF
330 test_expect_equal_file EXPECTED OUTPUT
331
332 test_begin_subtest "msg.get_properties (python, prefix)"
333 test_python <<'EOF'
334 import notmuch
335 db = notmuch.Database(mode=notmuch.Database.MODE.READ_ONLY)
336 msg = db.find_message("4EFC743A.3060609@april.org")
337 for (key,val) in msg.get_properties("testkey"):
338         print("{0} = {1}".format(key,val))
339 EOF
340 cat <<'EOF' > EXPECTED
341 testkey1 = alice
342 testkey1 = bob
343 testkey1 = testvalue1
344 testkey1 = testvalue2
345 testkey3 = alice3
346 testkey3 = bob3
347 testkey3 = testvalue3
348 EOF
349 test_expect_equal_file EXPECTED OUTPUT
350
351 test_begin_subtest "msg.get_properties (python, exact)"
352 test_python <<'EOF'
353 import notmuch
354 db = notmuch.Database(mode=notmuch.Database.MODE.READ_ONLY)
355 msg = db.find_message("4EFC743A.3060609@april.org")
356 for (key,val) in msg.get_properties("testkey",True):
357         print("{0} = {1}".format(key,val))
358 EOF
359 test_expect_equal_file /dev/null OUTPUT
360
361 test_done