1#!/usr/bin/env bash
2test_description="library config API"
3
4. $(dirname "$0")/test-lib.sh || exit 1
5
6add_email_corpus
7
8_libconfig_sanitize() {
9    ${NOTMUCH_PYTHON} /dev/fd/3 3<<'EOF'
10import os, sys, pwd, socket
11
12pw = pwd.getpwuid(os.getuid())
13user = pw.pw_name
14name = pw.pw_gecos.partition(",")[0]
15
16for l in sys.stdin:
17    if l[:4] == "08: ":
18        l = l.replace(user, "USERNAME", 1)
19    elif l[:4] == "10: ":
20        l = l.replace("'" + name, "'USER_FULL_NAME", 1)
21    sys.stdout.write(l)
22EOF
23}
24
25cat <<EOF > c_head
26#include <string.h>
27#include <stdlib.h>
28#include <notmuch-test.h>
29
30int main (int argc, char** argv)
31{
32   notmuch_database_t *db;
33   char *val;
34   notmuch_status_t stat;
35   char *msg = NULL;
36
37   for (int i = 1; i < argc; i++)
38      if (strcmp (argv[i], "%NULL%") == 0) argv[i] = NULL;
39
40   stat = notmuch_database_open_with_config (argv[1],
41                                              NOTMUCH_DATABASE_MODE_READ_WRITE,
42                                              argv[2],
43                                              argv[3],
44                                              &db,
45                                              &msg);
46   if (stat != NOTMUCH_STATUS_SUCCESS) {
47     fprintf (stderr, "error opening database\n%s\n%s\n", notmuch_status_to_string (stat), msg ? msg : "");
48     exit (1);
49   }
50EOF
51
52cat <<EOF > c_tail
53   EXPECT0(notmuch_database_destroy(db));
54}
55EOF
56
57test_begin_subtest "notmuch_database_{set,get}_config"
58cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} ${NOTMUCH_CONFIG}
59{
60   EXPECT0(notmuch_database_set_config (db, "test.key1", "testvalue1"));
61   EXPECT0(notmuch_database_set_config (db, "test.key2", "testvalue2"));
62   EXPECT0(notmuch_database_get_config (db, "test.key1", &val));
63   printf("test.key1 = %s\n", val);
64   EXPECT0(notmuch_database_get_config (db, "test.key2", &val));
65   printf("test.key2 = %s\n", val);
66}
67EOF
68cat <<'EOF' >EXPECTED
69== stdout ==
70test.key1 = testvalue1
71test.key2 = testvalue2
72== stderr ==
73EOF
74test_expect_equal_file EXPECTED OUTPUT
75
76
77test_begin_subtest "notmuch_database_get_config_list: empty list"
78cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} ${NOTMUCH_CONFIG} %NULL%
79{
80   notmuch_config_list_t *list;
81   EXPECT0(notmuch_database_get_config_list (db, "nonexistent", &list));
82   printf("valid = %d\n", notmuch_config_list_valid (list));
83   notmuch_config_list_destroy (list);
84}
85EOF
86cat <<'EOF' >EXPECTED
87== stdout ==
88valid = 0
89== stderr ==
90EOF
91test_expect_equal_file EXPECTED OUTPUT
92
93test_begin_subtest "notmuch_database_get_config_list: closed db"
94cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR}
95{
96   notmuch_config_list_t *list;
97   EXPECT0(notmuch_database_close (db));
98   stat = notmuch_database_get_config_list (db, "nonexistent", &list);
99   printf("%d\n", stat == NOTMUCH_STATUS_XAPIAN_EXCEPTION);
100}
101EOF
102cat <<'EOF' >EXPECTED
103== stdout ==
1041
105== stderr ==
106EOF
107test_expect_equal_file EXPECTED OUTPUT
108
109test_begin_subtest "notmuch_database_get_config_list: all pairs"
110cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} ${NOTMUCH_CONFIG} %NULL%
111{
112   notmuch_config_list_t *list;
113   EXPECT0(notmuch_database_set_config (db, "zzzafter", "afterval"));
114   EXPECT0(notmuch_database_set_config (db, "aaabefore", "beforeval"));
115   EXPECT0(notmuch_database_get_config_list (db, "", &list));
116   for (; notmuch_config_list_valid (list); notmuch_config_list_move_to_next (list)) {
117      printf("%s %s\n", notmuch_config_list_key (list), notmuch_config_list_value(list));
118   }
119   notmuch_config_list_destroy (list);
120}
121EOF
122cat <<'EOF' >EXPECTED
123== stdout ==
124aaabefore beforeval
125test.key1 testvalue1
126test.key2 testvalue2
127zzzafter afterval
128== stderr ==
129EOF
130test_expect_equal_file EXPECTED OUTPUT
131
132test_begin_subtest "notmuch_database_get_config_list: all pairs (closed db)"
133cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR}
134{
135   notmuch_config_list_t *list;
136   EXPECT0(notmuch_database_get_config_list (db, "", &list));
137   EXPECT0(notmuch_database_close (db));
138   for (; notmuch_config_list_valid (list); notmuch_config_list_move_to_next (list)) {
139      printf("%s %d\n", notmuch_config_list_key (list), NULL == notmuch_config_list_value(list));
140   }
141   notmuch_config_list_destroy (list);
142}
143EOF
144cat <<'EOF' >EXPECTED
145== stdout ==
146aaabefore 1
147test.key1 1
148test.key2 1
149zzzafter 1
150== stderr ==
151EOF
152test_expect_equal_file EXPECTED OUTPUT
153
154test_begin_subtest "notmuch_database_get_config_list: one prefix"
155cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} ${NOTMUCH_CONFIG} %NULL%
156{
157   notmuch_config_list_t *list;
158   EXPECT0(notmuch_database_get_config_list (db, "test.key", &list));
159   for (; notmuch_config_list_valid (list); notmuch_config_list_move_to_next (list)) {
160      printf("%s %s\n", notmuch_config_list_key (list), notmuch_config_list_value(list));
161   }
162   notmuch_config_list_destroy (list);
163}
164EOF
165cat <<'EOF' >EXPECTED
166== stdout ==
167test.key1 testvalue1
168test.key2 testvalue2
169== stderr ==
170EOF
171test_expect_equal_file EXPECTED OUTPUT
172
173test_begin_subtest "dump config"
174cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} ${NOTMUCH_CONFIG} %NULL%
175{
176    EXPECT0(notmuch_database_set_config (db, "key with spaces", "value, with, spaces!"));
177}
178EOF
179notmuch dump --include=config >OUTPUT
180cat <<'EOF' >EXPECTED
181#notmuch-dump batch-tag:3 config
182#@ aaabefore beforeval
183#@ key%20with%20spaces value,%20with,%20spaces%21
184#@ test.key1 testvalue1
185#@ test.key2 testvalue2
186#@ zzzafter afterval
187EOF
188test_expect_equal_file EXPECTED OUTPUT
189
190test_begin_subtest "restore config"
191notmuch dump --include=config >EXPECTED
192cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} ${NOTMUCH_CONFIG} %NULL%
193{
194    EXPECT0(notmuch_database_set_config (db, "test.key1", "mutatedvalue"));
195}
196EOF
197notmuch restore --include=config <EXPECTED
198notmuch dump --include=config >OUTPUT
199test_expect_equal_file EXPECTED OUTPUT
200
201backup_database
202test_begin_subtest "override config from file"
203notmuch config set test.key1 overridden
204cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} ${NOTMUCH_CONFIG}
205{
206   EXPECT0(notmuch_database_get_config (db, "test.key1", &val));
207   printf("test.key1 = %s\n", val);
208   EXPECT0(notmuch_database_get_config (db, "test.key2", &val));
209   printf("test.key2 = %s\n", val);
210}
211EOF
212cat <<'EOF' >EXPECTED
213== stdout ==
214test.key1 = overridden
215test.key2 = testvalue2
216== stderr ==
217EOF
218test_expect_equal_file EXPECTED OUTPUT
219restore_database
220
221test_begin_subtest "NOTMUCH_CONFIG_HOOK_DIR: traditional"
222cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} ${NOTMUCH_CONFIG} %NULL%
223{
224   const char *val = notmuch_config_get (db, NOTMUCH_CONFIG_HOOK_DIR);
225   printf("database.hook_dir = %s\n", val);
226}
227EOF
228cat <<'EOF' >EXPECTED
229== stdout ==
230database.hook_dir = MAIL_DIR/.notmuch/hooks
231== stderr ==
232EOF
233test_expect_equal_file EXPECTED OUTPUT
234
235test_begin_subtest "NOTMUCH_CONFIG_HOOK_DIR: xdg"
236dir="${HOME}/.config/notmuch/default/hooks"
237mkdir -p $dir
238cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} ${NOTMUCH_CONFIG} %NULL%
239{
240   const char *val = notmuch_config_get (db, NOTMUCH_CONFIG_HOOK_DIR);
241   printf("database.hook_dir = %s\n", val);
242}
243EOF
244cat <<'EOF' >EXPECTED
245== stdout ==
246database.hook_dir = CWD/home/.config/notmuch/default/hooks
247== stderr ==
248EOF
249rmdir $dir
250test_expect_equal_file EXPECTED OUTPUT
251
252test_begin_subtest "notmuch_config_get_values"
253cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} ${NOTMUCH_CONFIG} %NULL%
254{
255    notmuch_config_values_t *values;
256    EXPECT0(notmuch_config_set (db, NOTMUCH_CONFIG_NEW_TAGS, "a;b;c"));
257    for (values = notmuch_config_get_values (db, NOTMUCH_CONFIG_NEW_TAGS);
258	 notmuch_config_values_valid (values);
259	 notmuch_config_values_move_to_next (values))
260    {
261	  puts (notmuch_config_values_get (values));
262    }
263}
264EOF
265cat <<'EOF' >EXPECTED
266== stdout ==
267a
268b
269c
270== stderr ==
271EOF
272test_expect_equal_file EXPECTED OUTPUT
273restore_database
274
275test_begin_subtest "notmuch_config_get_values_string"
276cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} ${NOTMUCH_CONFIG} %NULL%
277{
278    notmuch_config_values_t *values;
279    EXPECT0(notmuch_database_set_config (db, "test.list", "x;y;z"));
280    for (values = notmuch_config_get_values_string (db, "test.list");
281	 notmuch_config_values_valid (values);
282	 notmuch_config_values_move_to_next (values))
283    {
284	  puts (notmuch_config_values_get (values));
285    }
286}
287EOF
288cat <<'EOF' >EXPECTED
289== stdout ==
290x
291y
292z
293== stderr ==
294EOF
295test_expect_equal_file EXPECTED OUTPUT
296restore_database
297
298test_begin_subtest "notmuch_config_get_values (restart)"
299cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} ${NOTMUCH_CONFIG} %NULL%
300{
301    notmuch_config_values_t *values;
302    EXPECT0(notmuch_config_set (db, NOTMUCH_CONFIG_NEW_TAGS, "a;b;c"));
303    for (values = notmuch_config_get_values (db, NOTMUCH_CONFIG_NEW_TAGS);
304	 notmuch_config_values_valid (values);
305	 notmuch_config_values_move_to_next (values))
306    {
307	  puts (notmuch_config_values_get (values));
308    }
309    for (notmuch_config_values_start (values);
310	 notmuch_config_values_valid (values);
311	 notmuch_config_values_move_to_next (values))
312    {
313	  puts (notmuch_config_values_get (values));
314    }
315}
316EOF
317cat <<'EOF' >EXPECTED
318== stdout ==
319a
320b
321c
322a
323b
324c
325== stderr ==
326EOF
327test_expect_equal_file EXPECTED OUTPUT
328restore_database
329
330backup_database
331test_begin_subtest "notmuch_config_get_values, trailing ;"
332cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} ${NOTMUCH_CONFIG} %NULL%
333{
334    notmuch_config_values_t *values;
335    EXPECT0(notmuch_config_set (db, NOTMUCH_CONFIG_NEW_TAGS, "a;b;c"));
336    for (values = notmuch_config_get_values (db, NOTMUCH_CONFIG_NEW_TAGS);
337	 notmuch_config_values_valid (values);
338	 notmuch_config_values_move_to_next (values))
339    {
340	  puts (notmuch_config_values_get (values));
341    }
342}
343EOF
344cat <<'EOF' >EXPECTED
345== stdout ==
346a
347b
348c
349== stderr ==
350EOF
351test_expect_equal_file EXPECTED OUTPUT
352restore_database
353
354backup_database
355test_begin_subtest "get config by key"
356cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} ${NOTMUCH_CONFIG}
357{
358   printf("before = %s\n", notmuch_config_get (db, NOTMUCH_CONFIG_SYNC_MAILDIR_FLAGS));
359   EXPECT0(notmuch_database_set_config (db, "maildir.synchronize_flags", "false"));
360   printf("after = %s\n", notmuch_config_get (db, NOTMUCH_CONFIG_SYNC_MAILDIR_FLAGS));
361}
362EOF
363cat <<'EOF' >EXPECTED
364== stdout ==
365before = true
366after = false
367== stderr ==
368EOF
369test_expect_equal_file EXPECTED OUTPUT
370restore_database
371
372backup_database
373test_begin_subtest "set config by key"
374notmuch config set test.key1 overridden
375cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} ${NOTMUCH_CONFIG}
376{
377   printf("before = %s\n", notmuch_config_get (db, NOTMUCH_CONFIG_SYNC_MAILDIR_FLAGS));
378   EXPECT0(notmuch_config_set (db, NOTMUCH_CONFIG_SYNC_MAILDIR_FLAGS, "false"));
379   printf("after = %s\n", notmuch_config_get (db, NOTMUCH_CONFIG_SYNC_MAILDIR_FLAGS));
380}
381EOF
382cat <<'EOF' >EXPECTED
383== stdout ==
384before = true
385after = false
386== stderr ==
387EOF
388test_expect_equal_file EXPECTED OUTPUT
389restore_database
390
391test_begin_subtest "load default values"
392export MAILDIR=${MAIL_DIR}
393cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} '' %NULL%
394{
395    notmuch_config_key_t key;
396    for (key = NOTMUCH_CONFIG_FIRST;
397	 key < NOTMUCH_CONFIG_LAST;
398	 key = (notmuch_config_key_t)(key + 1)) {
399	const char *val = notmuch_config_get (db, key);
400	printf("%02d: '%s'\n", key, val ? val : "NULL" );
401    }
402}
403EOF
404
405_libconfig_sanitize < OUTPUT > OUTPUT.clean
406
407cat <<'EOF' >EXPECTED
408== stdout ==
40900: 'MAIL_DIR'
41001: 'MAIL_DIR'
41102: 'MAIL_DIR/.notmuch/hooks'
41203: 'MAIL_DIR/.notmuch/backups'
41304: ''
41405: 'unread;inbox'
41506: ''
41607: 'true'
41708: 'USERNAME@localhost'
41809: 'NULL'
41910: 'USER_FULL_NAME'
42011: '8000'
421== stderr ==
422EOF
423unset MAILDIR
424test_expect_equal_file EXPECTED OUTPUT.clean
425
426backup_database
427test_begin_subtest "override config from \${NOTMUCH_CONFIG}"
428notmuch config set test.key1 overridden
429# second argument omitted to make argv[2] == NULL
430cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR}
431{
432   EXPECT0(notmuch_database_get_config (db, "test.key1", &val));
433   printf("test.key1 = %s\n", val);
434   EXPECT0(notmuch_database_get_config (db, "test.key2", &val));
435   printf("test.key2 = %s\n", val);
436}
437EOF
438notmuch config set test.key1
439cat <<'EOF' >EXPECTED
440== stdout ==
441test.key1 = overridden
442test.key2 = testvalue2
443== stderr ==
444EOF
445test_expect_equal_file EXPECTED OUTPUT
446restore_database
447
448backup_database
449test_begin_subtest "override config from \${HOME}/.notmuch-config"
450ovconfig=${HOME}/.notmuch-config
451cp ${NOTMUCH_CONFIG} ${ovconfig}
452old_NOTMUCH_CONFIG=${NOTMUCH_CONFIG}
453unset NOTMUCH_CONFIG
454notmuch --config=${ovconfig} config set test.key1 overridden-home
455cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} %NULL% %NULL%
456{
457   EXPECT0(notmuch_database_get_config (db, "test.key1", &val));
458   printf("test.key1 = %s\n", val);
459   EXPECT0(notmuch_database_get_config (db, "test.key2", &val));
460   printf("test.key2 = %s\n", val);
461}
462EOF
463rm -f ${ovconfig}
464export NOTMUCH_CONFIG=${old_NOTMUCH_CONFIG}
465cat <<'EOF' >EXPECTED
466== stdout ==
467test.key1 = overridden-home
468test.key2 = testvalue2
469== stderr ==
470EOF
471test_expect_equal_file EXPECTED OUTPUT
472restore_database
473
474backup_database
475test_begin_subtest "override config from \${XDG_CONFIG_HOME}/notmuch"
476ovconfig=${HOME}/.config/notmuch/default/config
477mkdir -p $(dirname ${ovconfig})
478cp ${NOTMUCH_CONFIG} ${ovconfig}
479old_NOTMUCH_CONFIG=${NOTMUCH_CONFIG}
480unset NOTMUCH_CONFIG
481notmuch --config=${ovconfig} config set test.key1 overridden-xdg
482cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} %NULL% %NULL%
483{
484   EXPECT0(notmuch_database_get_config (db, "test.key1", &val));
485   printf("test.key1 = %s\n", val);
486   EXPECT0(notmuch_database_get_config (db, "test.key2", &val));
487   printf("test.key2 = %s\n", val);
488}
489EOF
490rm -f ${ovconfig}
491export NOTMUCH_CONFIG=${old_NOTMUCH_CONFIG}
492cat <<'EOF' >EXPECTED
493== stdout ==
494test.key1 = overridden-xdg
495test.key2 = testvalue2
496== stderr ==
497EOF
498test_expect_equal_file EXPECTED OUTPUT
499restore_database
500
501backup_database
502test_begin_subtest "override config from \${XDG_CONFIG_HOME}/notmuch with profile"
503ovconfig=${HOME}/.config/notmuch/work/config
504mkdir -p $(dirname ${ovconfig})
505cp ${NOTMUCH_CONFIG} ${ovconfig}
506old_NOTMUCH_CONFIG=${NOTMUCH_CONFIG}
507unset NOTMUCH_CONFIG
508notmuch --config=${ovconfig} config set test.key1 overridden-xdg-profile
509cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} %NULL% work
510{
511   EXPECT0(notmuch_database_get_config (db, "test.key1", &val));
512   printf("test.key1 = %s\n", val);
513   EXPECT0(notmuch_database_get_config (db, "test.key2", &val));
514   printf("test.key2 = %s\n", val);
515}
516EOF
517rm -f ${ovconfig}
518export NOTMUCH_CONFIG=${old_NOTMUCH_CONFIG}
519cat <<'EOF' >EXPECTED
520== stdout ==
521test.key1 = overridden-xdg-profile
522test.key2 = testvalue2
523== stderr ==
524EOF
525test_expect_equal_file EXPECTED OUTPUT
526restore_database
527
528backup_database
529test_begin_subtest "override config from \${HOME}/.notmuch-config.work (via args)"
530ovconfig=${HOME}/.notmuch-config.work
531cp ${NOTMUCH_CONFIG} ${ovconfig}
532old_NOTMUCH_CONFIG=${NOTMUCH_CONFIG}
533unset NOTMUCH_CONFIG
534notmuch --config=${ovconfig} config set test.key1 overridden-profile
535cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} %NULL% work
536{
537   EXPECT0(notmuch_database_get_config (db, "test.key1", &val));
538   printf("test.key1 = %s\n", val);
539   EXPECT0(notmuch_database_get_config (db, "test.key2", &val));
540   printf("test.key2 = %s\n", val);
541}
542EOF
543#rm -f ${ovconfig}
544export NOTMUCH_CONFIG=${old_NOTMUCH_CONFIG}
545cat <<'EOF' >EXPECTED
546== stdout ==
547test.key1 = overridden-profile
548test.key2 = testvalue2
549== stderr ==
550EOF
551test_expect_equal_file EXPECTED OUTPUT
552restore_database
553
554test_begin_subtest "no config, fail to open database"
555old_NOTMUCH_CONFIG=${NOTMUCH_CONFIG}
556unset NOTMUCH_CONFIG
557cat c_head - c_tail <<'EOF' | test_C %NULL% '' %NULL%
558{
559   printf("NOT RUN");
560}
561EOF
562export NOTMUCH_CONFIG=${old_NOTMUCH_CONFIG}
563cat <<'EOF' >EXPECTED
564== stdout ==
565== stderr ==
566error opening database
567No database found
568Error: could not locate database.
569
570EOF
571test_expect_equal_file EXPECTED OUTPUT
572
573test_begin_subtest "open database from NOTMUCH_DATABASE"
574old_NOTMUCH_CONFIG=${NOTMUCH_CONFIG}
575unset NOTMUCH_CONFIG
576export NOTMUCH_DATABASE=${MAIL_DIR}
577cat c_head - c_tail <<'EOF' | test_C %NULL% '' %NULL%
578{
579   EXPECT0(notmuch_database_get_config (db, "test.key1", &val));
580   printf("test.key1 = %s\n", val);
581   EXPECT0(notmuch_database_get_config (db, "test.key2", &val));
582   printf("test.key2 = %s\n", val);
583}
584EOF
585export NOTMUCH_CONFIG=${old_NOTMUCH_CONFIG}
586unset NOTMUCH_DATABASE
587cat <<'EOF' >EXPECTED
588== stdout ==
589test.key1 = testvalue1
590test.key2 = testvalue2
591== stderr ==
592EOF
593test_expect_equal_file EXPECTED OUTPUT
594
595test_begin_subtest "NOTMUCH_DATABASE overrides config"
596cp notmuch-config notmuch-config.bak
597notmuch config set database.path /nonexistent
598export NOTMUCH_DATABASE=${MAIL_DIR}
599cat c_head - c_tail <<'EOF' | test_C %NULL% '' %NULL%
600{
601   EXPECT0(notmuch_database_get_config (db, "test.key1", &val));
602   printf("test.key1 = %s\n", val);
603   EXPECT0(notmuch_database_get_config (db, "test.key2", &val));
604   printf("test.key2 = %s\n", val);
605}
606EOF
607export NOTMUCH_CONFIG=${old_NOTMUCH_CONFIG}
608unset NOTMUCH_DATABASE
609cat <<'EOF' >EXPECTED
610== stdout ==
611test.key1 = testvalue1
612test.key2 = testvalue2
613== stderr ==
614EOF
615cp notmuch-config.bak notmuch-config
616test_expect_equal_file EXPECTED OUTPUT
617
618cat <<EOF > c_head2
619#include <string.h>
620#include <stdlib.h>
621#include <notmuch-test.h>
622
623int main (int argc, char** argv)
624{
625   notmuch_database_t *db;
626   char *val;
627   notmuch_status_t stat;
628   char *msg = NULL;
629
630   for (int i = 1; i < argc; i++)
631      if (strcmp (argv[i], "%NULL%") == 0) argv[i] = NULL;
632
633   stat = notmuch_database_load_config (argv[1],
634                                        argv[2],
635                                        argv[3],
636                                        &db,
637                                        &msg);
638   if (stat != NOTMUCH_STATUS_SUCCESS  && stat != NOTMUCH_STATUS_NO_CONFIG) {
639     fprintf (stderr, "error opening database\n%d: %s\n%s\n", stat,
640	      notmuch_status_to_string (stat), msg ? msg : "");
641     exit (1);
642   }
643EOF
644
645
646test_begin_subtest "notmuch_database_get_config (ndlc)"
647cat c_head2 - c_tail <<'EOF' | test_C ${MAIL_DIR} %NULL% %NULL%
648{
649   EXPECT0(notmuch_database_get_config (db, "test.key1", &val));
650   printf("test.key1 = %s\n", val);
651   EXPECT0(notmuch_database_get_config (db, "test.key2", &val));
652   printf("test.key2 = %s\n", val);
653}
654EOF
655cat <<'EOF' >EXPECTED
656== stdout ==
657test.key1 = testvalue1
658test.key2 = testvalue2
659== stderr ==
660EOF
661test_expect_equal_file EXPECTED OUTPUT
662
663
664test_begin_subtest "notmuch_database_get_config_list: all pairs (ndlc)"
665cat c_head2 - c_tail <<'EOF' | test_C ${MAIL_DIR} ${NOTMUCH_CONFIG} %NULL%
666{
667   notmuch_config_list_t *list;
668   EXPECT0(notmuch_database_get_config_list (db, "", &list));
669   for (; notmuch_config_list_valid (list); notmuch_config_list_move_to_next (list)) {
670      printf("%s %s\n", notmuch_config_list_key (list), notmuch_config_list_value(list));
671   }
672   notmuch_config_list_destroy (list);
673}
674EOF
675cat <<'EOF' >EXPECTED
676== stdout ==
677aaabefore beforeval
678key with spaces value, with, spaces!
679test.key1 testvalue1
680test.key2 testvalue2
681zzzafter afterval
682== stderr ==
683EOF
684test_expect_equal_file EXPECTED OUTPUT
685
686test_begin_subtest "notmuch_database_get_config_list: one prefix (ndlc)"
687cat c_head2 - c_tail <<'EOF' | test_C ${MAIL_DIR} ${NOTMUCH_CONFIG} %NULL%
688{
689   notmuch_config_list_t *list;
690   EXPECT0(notmuch_database_get_config_list (db, "test.key", &list));
691   for (; notmuch_config_list_valid (list); notmuch_config_list_move_to_next (list)) {
692      printf("%s %s\n", notmuch_config_list_key (list), notmuch_config_list_value(list));
693   }
694   notmuch_config_list_destroy (list);
695}
696EOF
697cat <<'EOF' >EXPECTED
698== stdout ==
699test.key1 testvalue1
700test.key2 testvalue2
701== stderr ==
702EOF
703test_expect_equal_file EXPECTED OUTPUT
704
705test_begin_subtest "list by keys (ndlc)"
706notmuch config set search.exclude_tags "foo;bar;fub"
707notmuch config set new.ignore "sekrit_junk"
708cat c_head2 - c_tail <<'EOF' | test_C ${MAIL_DIR} %NULL% %NULL%
709{
710    notmuch_config_key_t key;
711    for (key = NOTMUCH_CONFIG_FIRST;
712	 key < NOTMUCH_CONFIG_LAST;
713	 key = (notmuch_config_key_t)(key + 1)) {
714	const char *val = notmuch_config_get (db, key);
715	printf("%02d: '%s'\n", key, val ? val : "NULL" );
716    }
717}
718EOF
719cat <<'EOF' >EXPECTED
720== stdout ==
72100: 'MAIL_DIR'
72201: 'MAIL_DIR'
72302: 'MAIL_DIR/.notmuch/hooks'
72403: 'MAIL_DIR/.notmuch/backups'
72504: 'foo;bar;fub'
72605: 'unread;inbox'
72706: 'sekrit_junk'
72807: 'true'
72908: 'test_suite@notmuchmail.org'
73009: 'test_suite_other@notmuchmail.org;test_suite@otherdomain.org'
73110: 'Notmuch Test Suite'
73211: '8000'
733== stderr ==
734EOF
735test_expect_equal_file EXPECTED OUTPUT
736
737test_begin_subtest "load default values (ndlc, nonexistent config)"
738cat c_head2 - c_tail <<'EOF' | test_C ${MAIL_DIR} /nonexistent %NULL%
739{
740    notmuch_config_key_t key;
741    for (key = NOTMUCH_CONFIG_FIRST;
742	 key < NOTMUCH_CONFIG_LAST;
743	 key = (notmuch_config_key_t)(key + 1)) {
744	const char *val = notmuch_config_get (db, key);
745	printf("%02d: '%s'\n", key, val ? val : "NULL" );
746    }
747}
748EOF
749
750_libconfig_sanitize < OUTPUT > OUTPUT.clean
751
752cat <<'EOF' >EXPECTED
753== stdout ==
75400: 'MAIL_DIR'
75501: 'MAIL_DIR'
75602: 'MAIL_DIR/.notmuch/hooks'
75703: 'MAIL_DIR/.notmuch/backups'
75804: ''
75905: 'unread;inbox'
76006: ''
76107: 'true'
76208: 'USERNAME@localhost'
76309: 'NULL'
76410: 'USER_FULL_NAME'
76511: '8000'
766== stderr ==
767EOF
768test_expect_equal_file EXPECTED OUTPUT.clean
769
770backup_database
771test_begin_subtest "override config from \${HOME}/.notmuch-config (ndlc)"
772ovconfig=${HOME}/.notmuch-config
773cp ${NOTMUCH_CONFIG} ${ovconfig}
774old_NOTMUCH_CONFIG=${NOTMUCH_CONFIG}
775unset NOTMUCH_CONFIG
776notmuch --config=${ovconfig} config set test.key1 overridden-home
777cat c_head2 - c_tail <<'EOF' | test_C ${MAIL_DIR} %NULL% %NULL%
778{
779   EXPECT0(notmuch_database_get_config (db, "test.key1", &val));
780   printf("test.key1 = %s\n", val);
781   EXPECT0(notmuch_database_get_config (db, "test.key2", &val));
782   printf("test.key2 = %s\n", val);
783}
784EOF
785rm -f ${ovconfig}
786export NOTMUCH_CONFIG=${old_NOTMUCH_CONFIG}
787cat <<'EOF' >EXPECTED
788== stdout ==
789test.key1 = overridden-home
790test.key2 = testvalue2
791== stderr ==
792EOF
793test_expect_equal_file EXPECTED OUTPUT
794restore_database
795
796test_begin_subtest "notmuch_config_get_pairs: prefix (ndlc)"
797cat c_head2 - c_tail <<'EOF' | test_C ${MAIL_DIR} ${NOTMUCH_CONFIG} %NULL%
798{
799   notmuch_config_pairs_t *list;
800   for (list =  notmuch_config_get_pairs (db, "user.");
801        notmuch_config_pairs_valid (list);
802        notmuch_config_pairs_move_to_next (list)) {
803     printf("%s %s\n", notmuch_config_pairs_key (list), notmuch_config_pairs_value(list));
804   }
805   notmuch_config_pairs_destroy (list);
806}
807EOF
808cat <<'EOF' >EXPECTED
809== stdout ==
810user.name Notmuch Test Suite
811user.other_email test_suite_other@notmuchmail.org;test_suite@otherdomain.org
812user.primary_email test_suite@notmuchmail.org
813== stderr ==
814EOF
815test_expect_equal_file EXPECTED OUTPUT
816
817test_begin_subtest "notmuch_config_get_pairs: all pairs (ndlc)"
818cat c_head2 - c_tail <<'EOF' | test_C ${MAIL_DIR} ${NOTMUCH_CONFIG} %NULL%
819{
820   notmuch_config_pairs_t *list;
821   for (list =  notmuch_config_get_pairs (db, "");
822        notmuch_config_pairs_valid (list);
823        notmuch_config_pairs_move_to_next (list)) {
824     printf("%s %s\n", notmuch_config_pairs_key (list), notmuch_config_pairs_value(list));
825   }
826   notmuch_config_pairs_destroy (list);
827}
828EOF
829cat <<'EOF' >EXPECTED
830== stdout ==
831aaabefore beforeval
832database.autocommit 8000
833database.backup_dir MAIL_DIR/.notmuch/backups
834database.hook_dir MAIL_DIR/.notmuch/hooks
835database.mail_root MAIL_DIR
836database.path MAIL_DIR
837key with spaces value, with, spaces!
838maildir.synchronize_flags true
839new.ignore sekrit_junk
840new.tags unread;inbox
841search.exclude_tags foo;bar;fub
842test.key1 testvalue1
843test.key2 testvalue2
844user.name Notmuch Test Suite
845user.other_email test_suite_other@notmuchmail.org;test_suite@otherdomain.org
846user.primary_email test_suite@notmuchmail.org
847zzzafter afterval
848== stderr ==
849EOF
850test_expect_equal_file EXPECTED OUTPUT
851
852cat <<EOF > c_head3
853#include <notmuch-test.h>
854int main (int argc, char **argv) {
855  notmuch_status_t stat;
856  notmuch_database_t *db = NULL;
857EOF
858
859cat <<EOF > c_tail3
860  printf("db == NULL: %d\n", db == NULL);
861}
862EOF
863
864test_begin_subtest "open: database set to null on missing config"
865cat c_head3 - c_tail3 <<'EOF' | test_C ${MAIL_DIR}
866  notmuch_status_t st = notmuch_database_open_with_config(argv[1],
867							  NOTMUCH_DATABASE_MODE_READ_ONLY,
868							  "/nonexistent", NULL, &db, NULL);
869EOF
870cat <<EOF> EXPECTED
871== stdout ==
872db == NULL: 1
873== stderr ==
874EOF
875test_expect_equal_file EXPECTED OUTPUT
876
877test_begin_subtest "open: database set to null on missing config (env)"
878old_NOTMUCH_CONFIG=${NOTMUCH_CONFIG}
879export NOTMUCH_CONFIG="/nonexistent"
880cat c_head3 - c_tail3 <<'EOF' | test_C ${MAIL_DIR}
881  notmuch_status_t st = notmuch_database_open_with_config(argv[1],
882							  NOTMUCH_DATABASE_MODE_READ_ONLY,
883							  NULL, NULL, &db, NULL);
884EOF
885export NOTMUCH_CONFIG=${old_NOTMUCH_CONFIG}
886cat <<EOF> EXPECTED
887== stdout ==
888db == NULL: 1
889== stderr ==
890EOF
891test_expect_equal_file EXPECTED OUTPUT
892
893test_begin_subtest "create: database set to null on missing config"
894cat c_head3 - c_tail3 <<'EOF' | test_C ${MAIL_DIR} "/nonexistent"
895  notmuch_status_t st = notmuch_database_create_with_config(argv[1],argv[2], NULL, &db, NULL);
896EOF
897cat <<EOF> EXPECTED
898== stdout ==
899db == NULL: 1
900== stderr ==
901EOF
902test_expect_equal_file EXPECTED OUTPUT
903
904test_begin_subtest "create: database set to null on missing config (env)"
905old_NOTMUCH_CONFIG=${NOTMUCH_CONFIG}
906export NOTMUCH_CONFIG="/nonexistent"
907cat c_head3 - c_tail3 <<'EOF' | test_C ${MAIL_DIR}
908  notmuch_status_t st = notmuch_database_create_with_config(argv[1],
909							  NULL, NULL, &db, NULL);
910EOF
911export NOTMUCH_CONFIG=${old_NOTMUCH_CONFIG}
912cat <<EOF> EXPECTED
913== stdout ==
914db == NULL: 1
915== stderr ==
916EOF
917test_expect_equal_file EXPECTED OUTPUT
918
919test_begin_subtest "load_config: database set non-null on missing config"
920cat c_head3 - c_tail3 <<'EOF' | test_C ${MAIL_DIR} "/nonexistent"
921  notmuch_status_t st = notmuch_database_load_config(argv[1],argv[2], NULL, &db, NULL);
922EOF
923cat <<EOF> EXPECTED
924== stdout ==
925db == NULL: 0
926== stderr ==
927EOF
928test_expect_equal_file EXPECTED OUTPUT
929
930test_begin_subtest "load_config: database non-null on missing config (env)"
931old_NOTMUCH_CONFIG=${NOTMUCH_CONFIG}
932export NOTMUCH_CONFIG="/nonexistent"
933cat c_head3 - c_tail3 <<'EOF' | test_C ${MAIL_DIR}
934  notmuch_status_t st = notmuch_database_load_config(argv[1], NULL, NULL, &db, NULL);
935EOF
936export NOTMUCH_CONFIG=${old_NOTMUCH_CONFIG}
937cat <<EOF> EXPECTED
938== stdout ==
939db == NULL: 0
940== stderr ==
941EOF
942test_expect_equal_file EXPECTED OUTPUT
943
944test_begin_subtest "load_config: database set to NULL on fatal error"
945cat c_head3 - c_tail3 <<'EOF' | test_C
946  notmuch_status_t st = notmuch_database_load_config("relative", NULL, NULL, &db, NULL);
947EOF
948cat <<EOF> EXPECTED
949== stdout ==
950db == NULL: 1
951== stderr ==
952EOF
953test_expect_equal_file EXPECTED OUTPUT
954
955test_begin_subtest "open: database parameter overrides implicit config"
956notmuch config set database.path ${MAIL_DIR}/nonexistent
957cat c_head3 - c_tail3 <<'EOF' | test_C ${MAIL_DIR}
958  const char *path = NULL;
959  notmuch_status_t st = notmuch_database_open_with_config(argv[1],
960							  NOTMUCH_DATABASE_MODE_READ_ONLY,
961							  NULL, NULL, &db, NULL);
962  printf ("status: %d\n", st);
963  path = notmuch_database_get_path (db);
964  printf ("path: %s\n", path ? path : "(null)");
965EOF
966cat <<EOF> EXPECTED
967== stdout ==
968status: 0
969path: MAIL_DIR
970db == NULL: 0
971== stderr ==
972EOF
973notmuch_dir_sanitize < OUTPUT > OUTPUT.clean
974test_expect_equal_file EXPECTED OUTPUT.clean
975
976test_done
977