+cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} ${NOTMUCH_CONFIG} %NULL%
+{
+ notmuch_config_list_t *list;
+ EXPECT0(notmuch_database_get_config_list (db, "test.key", &list));
+ for (; notmuch_config_list_valid (list); notmuch_config_list_move_to_next (list)) {
+ printf("%s %s\n", notmuch_config_list_key (list), notmuch_config_list_value(list));
+ }
+ notmuch_config_list_destroy (list);
+}
+EOF
+cat <<'EOF' >EXPECTED
+== stdout ==
+test.key1 testvalue1
+test.key2 testvalue2
+== stderr ==
+EOF
+test_expect_equal_file EXPECTED OUTPUT
+
+test_begin_subtest "dump config"
+cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} ${NOTMUCH_CONFIG} %NULL%
+{
+ EXPECT0(notmuch_database_set_config (db, "key with spaces", "value, with, spaces!"));
+}
+EOF
+notmuch dump --include=config >OUTPUT
+cat <<'EOF' >EXPECTED
+#notmuch-dump batch-tag:3 config
+#@ aaabefore beforeval
+#@ key%20with%20spaces value,%20with,%20spaces%21
+#@ test.key1 testvalue1
+#@ test.key2 testvalue2
+#@ zzzafter afterval
+EOF
+test_expect_equal_file EXPECTED OUTPUT
+
+test_begin_subtest "restore config"
+notmuch dump --include=config >EXPECTED
+cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} ${NOTMUCH_CONFIG} %NULL%
+{
+ EXPECT0(notmuch_database_set_config (db, "test.key1", "mutatedvalue"));
+}
+EOF
+notmuch restore --include=config <EXPECTED
+notmuch dump --include=config >OUTPUT
+test_expect_equal_file EXPECTED OUTPUT
+
+backup_database
+test_begin_subtest "override config from file"
+notmuch config set test.key1 overridden
+cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} ${NOTMUCH_CONFIG}
+{
+ EXPECT0(notmuch_database_get_config (db, "test.key1", &val));
+ printf("test.key1 = %s\n", val);
+ EXPECT0(notmuch_database_get_config (db, "test.key2", &val));
+ printf("test.key2 = %s\n", val);
+}
+EOF
+cat <<'EOF' >EXPECTED
+== stdout ==
+test.key1 = overridden
+test.key2 = testvalue2
+== stderr ==
+EOF
+test_expect_equal_file EXPECTED OUTPUT
+restore_database
+
+test_begin_subtest "NOTMUCH_CONFIG_HOOK_DIR: traditional"
+cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} ${NOTMUCH_CONFIG} %NULL%
+{
+ const char *val = notmuch_config_get (db, NOTMUCH_CONFIG_HOOK_DIR);
+ printf("database.hook_dir = %s\n", val);
+}
+EOF
+cat <<'EOF' >EXPECTED
+== stdout ==
+database.hook_dir = MAIL_DIR/.notmuch/hooks
+== stderr ==
+EOF
+test_expect_equal_file EXPECTED OUTPUT
+
+test_begin_subtest "NOTMUCH_CONFIG_HOOK_DIR: xdg"
+dir="${HOME}/.config/notmuch/default/hooks"
+mkdir -p $dir
+cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} ${NOTMUCH_CONFIG} %NULL%
+{
+ const char *val = notmuch_config_get (db, NOTMUCH_CONFIG_HOOK_DIR);
+ printf("database.hook_dir = %s\n", val);
+}
+EOF
+cat <<'EOF' >EXPECTED
+== stdout ==
+database.hook_dir = CWD/home/.config/notmuch/default/hooks
+== stderr ==
+EOF
+rmdir $dir
+test_expect_equal_file EXPECTED OUTPUT
+
+test_begin_subtest "notmuch_config_get_values"
+cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} ${NOTMUCH_CONFIG} %NULL%
+{
+ notmuch_config_values_t *values;
+ EXPECT0(notmuch_config_set (db, NOTMUCH_CONFIG_NEW_TAGS, "a;b;c"));
+ for (values = notmuch_config_get_values (db, NOTMUCH_CONFIG_NEW_TAGS);
+ notmuch_config_values_valid (values);
+ notmuch_config_values_move_to_next (values))
+ {
+ puts (notmuch_config_values_get (values));
+ }
+}
+EOF
+cat <<'EOF' >EXPECTED
+== stdout ==
+a
+b
+c
+== stderr ==
+EOF
+test_expect_equal_file EXPECTED OUTPUT
+restore_database
+
+test_begin_subtest "notmuch_config_get_values (ignore leading/trailing whitespace)"
+cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} ${NOTMUCH_CONFIG} %NULL%
+{
+ notmuch_config_values_t *values;
+ EXPECT0(notmuch_config_set (db, NOTMUCH_CONFIG_NEW_TAGS, " a ; b c ; d "));
+ for (values = notmuch_config_get_values (db, NOTMUCH_CONFIG_NEW_TAGS);
+ notmuch_config_values_valid (values);
+ notmuch_config_values_move_to_next (values))
+ {
+ puts (notmuch_config_values_get (values));
+ }
+}
+EOF
+cat <<'EOF' >EXPECTED
+== stdout ==
+a
+b c
+d
+== stderr ==
+EOF
+test_expect_equal_file EXPECTED OUTPUT
+restore_database
+
+test_begin_subtest "notmuch_config_get_values_string"
+cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} ${NOTMUCH_CONFIG} %NULL%
+{
+ notmuch_config_values_t *values;
+ EXPECT0(notmuch_database_set_config (db, "test.list", "x;y;z"));
+ for (values = notmuch_config_get_values_string (db, "test.list");
+ notmuch_config_values_valid (values);
+ notmuch_config_values_move_to_next (values))
+ {
+ puts (notmuch_config_values_get (values));
+ }
+}
+EOF
+cat <<'EOF' >EXPECTED
+== stdout ==
+x
+y
+z
+== stderr ==
+EOF
+test_expect_equal_file EXPECTED OUTPUT
+restore_database
+
+test_begin_subtest "notmuch_config_get_values (restart)"
+cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} ${NOTMUCH_CONFIG} %NULL%
+{
+ notmuch_config_values_t *values;
+ EXPECT0(notmuch_config_set (db, NOTMUCH_CONFIG_NEW_TAGS, "a;b;c"));
+ for (values = notmuch_config_get_values (db, NOTMUCH_CONFIG_NEW_TAGS);
+ notmuch_config_values_valid (values);
+ notmuch_config_values_move_to_next (values))
+ {
+ puts (notmuch_config_values_get (values));
+ }
+ for (notmuch_config_values_start (values);
+ notmuch_config_values_valid (values);
+ notmuch_config_values_move_to_next (values))
+ {
+ puts (notmuch_config_values_get (values));
+ }
+}
+EOF
+cat <<'EOF' >EXPECTED
+== stdout ==
+a
+b
+c
+a
+b
+c
+== stderr ==
+EOF
+test_expect_equal_file EXPECTED OUTPUT
+restore_database
+
+backup_database
+test_begin_subtest "notmuch_config_get_values, trailing ;"
+cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} ${NOTMUCH_CONFIG} %NULL%
+{
+ notmuch_config_values_t *values;
+ EXPECT0(notmuch_config_set (db, NOTMUCH_CONFIG_NEW_TAGS, "a;b;c"));
+ for (values = notmuch_config_get_values (db, NOTMUCH_CONFIG_NEW_TAGS);
+ notmuch_config_values_valid (values);
+ notmuch_config_values_move_to_next (values))
+ {
+ puts (notmuch_config_values_get (values));
+ }
+}
+EOF
+cat <<'EOF' >EXPECTED
+== stdout ==
+a
+b
+c
+== stderr ==
+EOF
+test_expect_equal_file EXPECTED OUTPUT
+restore_database
+
+backup_database
+test_begin_subtest "get config by key"
+cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} ${NOTMUCH_CONFIG}
+{
+ printf("before = %s\n", notmuch_config_get (db, NOTMUCH_CONFIG_SYNC_MAILDIR_FLAGS));
+ EXPECT0(notmuch_database_set_config (db, "maildir.synchronize_flags", "false"));
+ printf("after = %s\n", notmuch_config_get (db, NOTMUCH_CONFIG_SYNC_MAILDIR_FLAGS));
+}
+EOF
+cat <<'EOF' >EXPECTED
+== stdout ==
+before = true
+after = false
+== stderr ==
+EOF
+test_expect_equal_file EXPECTED OUTPUT
+restore_database
+
+backup_database
+test_begin_subtest "set config by key"
+notmuch config set test.key1 overridden
+cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} ${NOTMUCH_CONFIG}
+{
+ printf("before = %s\n", notmuch_config_get (db, NOTMUCH_CONFIG_SYNC_MAILDIR_FLAGS));
+ EXPECT0(notmuch_config_set (db, NOTMUCH_CONFIG_SYNC_MAILDIR_FLAGS, "false"));
+ printf("after = %s\n", notmuch_config_get (db, NOTMUCH_CONFIG_SYNC_MAILDIR_FLAGS));
+}
+EOF
+cat <<'EOF' >EXPECTED
+== stdout ==
+before = true
+after = false
+== stderr ==
+EOF
+test_expect_equal_file EXPECTED OUTPUT
+restore_database
+
+test_begin_subtest "load default values"
+export MAILDIR=${MAIL_DIR}
+cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR} '' %NULL%
+{
+ notmuch_config_key_t key;
+ for (key = NOTMUCH_CONFIG_FIRST;
+ key < NOTMUCH_CONFIG_LAST;
+ key = (notmuch_config_key_t)(key + 1)) {
+ const char *val = notmuch_config_get (db, key);
+ printf("%02d: '%s'\n", key, val ? val : "NULL" );
+ }
+}
+EOF
+
+_libconfig_sanitize < OUTPUT > OUTPUT.clean
+
+cat <<'EOF' >EXPECTED
+== stdout ==
+00: 'MAIL_DIR'
+01: 'MAIL_DIR'
+02: 'MAIL_DIR/.notmuch/hooks'
+03: 'MAIL_DIR/.notmuch/backups'
+04: ''
+05: 'unread;inbox'
+06: ''
+07: 'true'
+08: 'USERNAME@localhost'
+09: 'NULL'
+10: 'USER_FULL_NAME'
+11: '8000'
+12: 'NULL'
+== stderr ==
+EOF
+unset MAILDIR
+test_expect_equal_file EXPECTED OUTPUT.clean
+
+backup_database
+test_begin_subtest "override config from \${NOTMUCH_CONFIG}"
+notmuch config set test.key1 overridden
+# second argument omitted to make argv[2] == NULL