2 test_description="message property API"
4 . $(dirname "$0")/test-lib.sh || exit 1
9 #include <notmuch-test.h>
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));
17 notmuch_message_properties_destroy (list);
20 int main (int argc, char** argv)
22 notmuch_database_t *db;
23 notmuch_message_t *message = NULL;
25 notmuch_status_t stat;
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");
36 EXPECT0(notmuch_database_destroy(db));
40 test_begin_subtest "notmuch_message_{add,get,remove}_property"
41 cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR}
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));
51 EXPECT0(notmuch_message_get_property (message, "testkey2", &val));
52 printf("testkey2 = %s\n", val);
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);
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);
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);
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);
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
86 test_expect_equal_file EXPECTED OUTPUT
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);
97 test_expect_equal_file EXPECTED OUTPUT
99 test_begin_subtest "testing string map binary search (via message properties)"
100 cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR}
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]));
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);
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);
132 test_expect_equal_file EXPECTED OUTPUT
134 test_begin_subtest "notmuch_message_get_properties: empty list"
135 cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR}
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);
143 cat <<'EOF' >EXPECTED
148 test_expect_equal_file EXPECTED OUTPUT
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);
154 cat <<'EOF' >EXPECTED
159 test_expect_equal_file EXPECTED OUTPUT
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);
168 cat <<'EOF' >EXPECTED
176 test_expect_equal_file EXPECTED OUTPUT
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);
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
197 cat <<'EOF' >EXPECTED
208 test_expect_equal_file EXPECTED OUTPUT
210 test_begin_subtest "notmuch_message_properties: modify during iteration"
211 cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR}
213 const char *keys[1000] = {NULL};
214 const char *vals[1000] = {NULL};
215 notmuch_message_properties_t *properties;
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++)
222 const char *key, *value;
224 keys[i]=talloc_strdup(message,
225 notmuch_message_properties_key (properties));
226 vals[i]=talloc_strdup(message,
227 notmuch_message_properties_value (properties));
229 EXPECT0(notmuch_message_remove_property (message, keys[i], vals[i]));
232 print_properties (message, "", FALSE);
234 for (i = 0; keys[i] && vals[i]; i++) {
235 EXPECT0(notmuch_message_add_property (message, keys[i], vals[i]));
239 cat <<'EOF' >EXPECTED
243 test_expect_equal_file EXPECTED OUTPUT
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
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 ="));
252 notmuch dump | grep '^#=' > OUTPUT
253 test_expect_equal_file PROPERTIES OUTPUT
255 test_begin_subtest "dump _only_ message properties"
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
260 notmuch dump --include=properties > OUTPUT
261 test_expect_equal_file EXPECTED OUTPUT
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"));
269 notmuch restore < BEFORE1
270 notmuch dump | grep '^#=' > OUTPUT
271 test_expect_equal_file PROPERTIES OUTPUT
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"));
279 notmuch restore < BEFORE2
280 notmuch dump | grep '^#=' > OUTPUT
281 test_expect_equal_file PROPERTIES OUTPUT
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"));
287 notmuch restore < BEFORE2
288 notmuch dump | grep '^#=' > OUTPUT
289 test_expect_equal_file PROPERTIES OUTPUT
291 test_begin_subtest "test 'property:' queries: empty"
292 notmuch search property:testkey1=charles > OUTPUT
293 test_expect_equal_file /dev/null OUTPUT
295 test_begin_subtest "test 'property:' queries: single message"
296 notmuch search --output=messages property:testkey1=alice > OUTPUT
298 id:4EFC743A.3060609@april.org
300 test_expect_equal_file EXPECTED OUTPUT
302 test_begin_subtest "msg.get_property (python)"
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")))
310 cat <<'EOF' > EXPECTED
314 test_expect_equal_file EXPECTED OUTPUT
316 test_begin_subtest "msg.get_properties (python)"
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))
324 cat <<'EOF' > EXPECTED
327 testkey1 = testvalue1
328 testkey1 = testvalue2
330 test_expect_equal_file EXPECTED OUTPUT
332 test_begin_subtest "msg.get_properties (python, prefix)"
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))
340 cat <<'EOF' > EXPECTED
343 testkey1 = testvalue1
344 testkey1 = testvalue2
347 testkey3 = testvalue3
349 test_expect_equal_file EXPECTED OUTPUT
351 test_begin_subtest "msg.get_properties (python, exact)"
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))
359 test_expect_equal_file /dev/null OUTPUT