aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rwxr-xr-xinterimap5
-rw-r--r--tests/00-db-exclusive/local.conf5
-rw-r--r--tests/00-db-exclusive/remote.conf5
-rw-r--r--tests/00-db-exclusive/run25
l---------tests/00-db-migration-0-to-1-delim-mismatch/before.sql1
-rw-r--r--tests/00-db-migration-0-to-1-delim-mismatch/local.conf6
-rw-r--r--tests/00-db-migration-0-to-1-delim-mismatch/remote.conf6
-rw-r--r--tests/00-db-migration-0-to-1-delim-mismatch/run8
-rw-r--r--tests/00-db-migration-0-to-1-foreign-key-violation/local.conf6
-rw-r--r--tests/00-db-migration-0-to-1-foreign-key-violation/remote.conf6
-rw-r--r--tests/00-db-migration-0-to-1-foreign-key-violation/run23
-rw-r--r--tests/00-db-migration-0-to-1/local.conf6
-rw-r--r--tests/00-db-migration-0-to-1/remote.conf6
-rw-r--r--tests/01-rename-exists-db/local.conf6
-rw-r--r--tests/01-rename-exists-db/remote.conf6
-rw-r--r--tests/01-rename-exists-local/local.conf6
-rw-r--r--tests/01-rename-exists-local/remote.conf6
-rw-r--r--tests/01-rename-exists-remote/local.conf6
-rw-r--r--tests/01-rename-exists-remote/remote.conf6
-rw-r--r--tests/01-rename/local.conf6
-rw-r--r--tests/01-rename/remote.conf6
-rw-r--r--tests/02-delete/local.conf6
-rw-r--r--tests/02-delete/remote.conf6
-rw-r--r--tests/03-sync-mailbox-list-partial/interimap.conf1
-rw-r--r--tests/03-sync-mailbox-list-partial/local.conf6
-rw-r--r--tests/03-sync-mailbox-list-partial/remote.conf6
-rw-r--r--tests/03-sync-mailbox-list-partial/run57
-rw-r--r--tests/03-sync-mailbox-list-ref/local.conf6
-rw-r--r--tests/03-sync-mailbox-list-ref/remote.conf6
-rw-r--r--tests/03-sync-mailbox-list-ref/run28
-rw-r--r--tests/03-sync-mailbox-list/local.conf6
-rw-r--r--tests/03-sync-mailbox-list/remote.conf6
-rw-r--r--tests/03-sync-mailbox-list/run73
-rw-r--r--tests/04-resume/local.conf6
-rw-r--r--tests/04-resume/remote.conf6
-rw-r--r--tests/05-repair/local.conf6
-rw-r--r--tests/05-repair/remote.conf6
-rw-r--r--tests/06-largeint/local.conf5
-rw-r--r--tests/06-largeint/remote.conf5
-rw-r--r--tests/07-sync-live-multi/remote.conf6
-rw-r--r--tests/07-sync-live-multi/remote2.conf6
-rw-r--r--tests/07-sync-live-multi/remote3.conf6
-rw-r--r--tests/07-sync-live/local.conf6
-rw-r--r--tests/07-sync-live/remote.conf6
-rw-r--r--tests/db-exclusive-lock/t16
-rw-r--r--tests/db-migration-0-1-foreign-key-violation/t21
-rw-r--r--tests/db-no-create--watch/t6
l---------tests/db-upgrade-0-1-delim-mismatch/before.sql1
-rw-r--r--tests/db-upgrade-0-1-delim-mismatch/local.conf3
-rw-r--r--tests/db-upgrade-0-1-delim-mismatch/remote.conf3
-rw-r--r--tests/db-upgrade-0-1-delim-mismatch/t7
-rw-r--r--tests/db-upgrade-0-1/after.sql (renamed from tests/00-db-migration-0-to-1/after.sql)0
-rw-r--r--tests/db-upgrade-0-1/before.sql (renamed from tests/00-db-migration-0-to-1/before.sql)0
-rw-r--r--tests/db-upgrade-0-1/local.conf3
l---------tests/db-upgrade-0-1/remote.conf1
-rw-r--r--tests/db-upgrade-0-1/t (renamed from tests/00-db-migration-0-to-1/run)11
-rw-r--r--tests/delete/local.conf3
-rw-r--r--tests/delete/remote.conf3
-rw-r--r--tests/delete/t (renamed from tests/02-delete/run)64
-rw-r--r--tests/ignore-mailbox/interimap.conf1
-rw-r--r--tests/ignore-mailbox/local.conf3
-rw-r--r--tests/ignore-mailbox/remote.conf3
-rw-r--r--tests/ignore-mailbox/t62
-rw-r--r--tests/largeint/t (renamed from tests/06-largeint/run)13
-rw-r--r--tests/list37
-rw-r--r--tests/list-mailbox/interimap.conf1
-rw-r--r--tests/list-mailbox/local.conf3
-rw-r--r--tests/list-mailbox/remote.conf3
-rw-r--r--tests/list-mailbox/t57
-rw-r--r--tests/list-reference/interimap.local1
-rw-r--r--tests/list-reference/interimap.remote1
-rw-r--r--tests/list-reference/local.conf3
-rw-r--r--tests/list-reference/remote.conf3
-rw-r--r--tests/list-reference/t47
-rw-r--r--tests/list-select-opts/interimap.conf1
-rw-r--r--tests/list-select-opts/local.conf3
-rw-r--r--tests/list-select-opts/remote.conf3
-rw-r--r--tests/list-select-opts/t56
-rw-r--r--tests/rename-exists-db/local.conf3
-rw-r--r--tests/rename-exists-db/remote.conf3
-rw-r--r--tests/rename-exists-db/t (renamed from tests/01-rename-exists-db/run)6
-rw-r--r--tests/rename-exists-local/local.conf3
-rw-r--r--tests/rename-exists-local/remote.conf3
-rw-r--r--tests/rename-exists-local/t (renamed from tests/01-rename-exists-local/run)6
-rw-r--r--tests/rename-exists-remote/local.conf3
-rw-r--r--tests/rename-exists-remote/remote.conf3
-rw-r--r--tests/rename-exists-remote/t (renamed from tests/01-rename-exists-remote/run)6
-rw-r--r--tests/rename-inferiors/local.conf3
-rw-r--r--tests/rename-inferiors/remote.conf3
-rw-r--r--tests/rename-inferiors/t (renamed from tests/01-rename/run)50
-rw-r--r--tests/rename-simple/t61
-rw-r--r--tests/repair/local.conf3
-rw-r--r--tests/repair/remote.conf3
-rw-r--r--tests/repair/t (renamed from tests/05-repair/run)32
-rw-r--r--tests/resume/local.conf3
-rw-r--r--tests/resume/remote.conf3
-rw-r--r--tests/resume/t (renamed from tests/04-resume/run)12
-rwxr-xr-xtests/run173
-rwxr-xr-xtests/run-all65
l---------tests/sync-live-crippled/local.conf1
-rw-r--r--tests/sync-live-crippled/remote.conf6
l---------tests/sync-live-crippled/t1
-rw-r--r--tests/sync-live-multi/interimap1.local1
-rw-r--r--tests/sync-live-multi/interimap2.local1
-rw-r--r--tests/sync-live-multi/interimap3.local1
-rw-r--r--tests/sync-live-multi/local.conf (renamed from tests/07-sync-live-multi/local.conf)0
-rw-r--r--tests/sync-live-multi/remote1.conf3
-rw-r--r--tests/sync-live-multi/remote2.conf3
-rw-r--r--tests/sync-live-multi/remote3.conf3
-rw-r--r--tests/sync-live-multi/remotes1
-rw-r--r--tests/sync-live-multi/t (renamed from tests/07-sync-live-multi/run)95
-rw-r--r--tests/sync-live/local.conf3
-rw-r--r--tests/sync-live/remote.conf3
-rw-r--r--tests/sync-live/t (renamed from tests/07-sync-live/run)42
-rw-r--r--tests/sync-mailbox-list/local.conf3
-rw-r--r--tests/sync-mailbox-list/remote.conf3
-rw-r--r--tests/sync-mailbox-list/t93
118 files changed, 944 insertions, 638 deletions
diff --git a/Makefile b/Makefile
index 4fc759f..fdfb717 100644
--- a/Makefile
+++ b/Makefile
@@ -33,7 +33,7 @@ $(MANUALS): %: %.md
pandoc -s -f json -t man+smart -o "$@"
test:
- @for t in tests/*; do if [ -f "$$t/run" ]; then ./tests/run "$$t" || exit 1; fi; done
+ @./tests/run-all
HTML_ROOTDIR ?= ./doc
CSS ?= /usr/share/javascript/bootstrap/css/bootstrap.min.css
diff --git a/interimap b/interimap
index f170ded..a409c65 100755
--- a/interimap
+++ b/interimap
@@ -396,7 +396,7 @@ fail(undef, "Local and remote namespaces are neither both flat nor both hierarch
fail(undef, "Local and remote hierachy delimiters differ ",
"(local ", print_delimiter($IMAP->{local}->{delimiter}), ", ",
"remote ", print_delimiter($IMAP->{remote}->{delimiter}), "), ",
- "refusing to update \`mailboxes\` table.")
+ "refusing to update table \`mailboxes\`.")
if defined $IMAP->{local}->{delimiter} and defined $IMAP->{remote}->{delimiter}
# we failed earlier if only one of them was NIL
and $IMAP->{local}->{delimiter} ne $IMAP->{remote}->{delimiter};
@@ -418,7 +418,7 @@ fail(undef, "Local and remote namespaces are neither both flat nor both hierarch
$DBH->do("DROP TABLE mailboxes");
$DBH->do("ALTER TABLE _tmp${DATABASE_VERSION}_mailboxes RENAME TO mailboxes");
}
- fail("database", "Broken referential integrity! Refusing to commit changes.")
+ fail("database", "Broken referential integrity! Refusing to commit changes.")
if defined $DBH->selectrow_arrayref("PRAGMA foreign_key_check");
SCHEMA_DONE:
$DBH->do("PRAGMA user_version = $DATABASE_VERSION");
@@ -530,6 +530,7 @@ if (defined $COMMAND and $COMMAND eq 'delete') {
qw/mapping local remote mailboxes/
if @ARGV and $CONFIG{target}->{database};
foreach my $mailbox (@ARGV) {
+ fail(undef, "INBOX can't be deleted") if uc($mailbox) eq "INBOX"; # RFC 3501 sec. 6.3.4
my $idx = db_get_mailbox_idx($mailbox);
# delete $mailbox on servers where $mailbox exists. note that
diff --git a/tests/00-db-exclusive/local.conf b/tests/00-db-exclusive/local.conf
deleted file mode 100644
index 9c838fd..0000000
--- a/tests/00-db-exclusive/local.conf
+++ /dev/null
@@ -1,5 +0,0 @@
-namespace inbox {
- location = maildir:~/inbox:LAYOUT=index
- inbox = yes
- list = yes
-}
diff --git a/tests/00-db-exclusive/remote.conf b/tests/00-db-exclusive/remote.conf
deleted file mode 100644
index 9c838fd..0000000
--- a/tests/00-db-exclusive/remote.conf
+++ /dev/null
@@ -1,5 +0,0 @@
-namespace inbox {
- location = maildir:~/inbox:LAYOUT=index
- inbox = yes
- list = yes
-}
diff --git a/tests/00-db-exclusive/run b/tests/00-db-exclusive/run
deleted file mode 100644
index 1528b3b..0000000
--- a/tests/00-db-exclusive/run
+++ /dev/null
@@ -1,25 +0,0 @@
-# verify that database isn't created in --watch mode
-! interimap --watch=60
-xgrep -E "^DBI connect\(.*\) failed: unable to open database file at " <"$STDERR"
-
-# now create database
-interimap
-
-# start a background process
-interimap --watch=60 & pid=$!
-cleanup() {
- # kill interimap process and its children
- pkill -P "$pid" -TERM || true
- kill -TERM "$pid" || true
- wait
-}
-trap cleanup EXIT INT TERM
-
-sleep .05 # wait a short while so we have time to lock the database (ugly and racy...)
-# verify that subsequent runs fail as we can't acquire the exclusive lock
-! interimap
-
-# line 177 is `$DBH->do("PRAGMA locking_mode = EXCLUSIVE");`
-xgrep -Fx "DBD::SQLite::db do failed: database is locked at ./interimap line 177." <"$STDERR"
-
-# vim: set filetype=sh :
diff --git a/tests/00-db-migration-0-to-1-delim-mismatch/before.sql b/tests/00-db-migration-0-to-1-delim-mismatch/before.sql
deleted file mode 120000
index 0abb9bf..0000000
--- a/tests/00-db-migration-0-to-1-delim-mismatch/before.sql
+++ /dev/null
@@ -1 +0,0 @@
-../00-db-migration-0-to-1/before.sql \ No newline at end of file
diff --git a/tests/00-db-migration-0-to-1-delim-mismatch/local.conf b/tests/00-db-migration-0-to-1-delim-mismatch/local.conf
deleted file mode 100644
index 08438cb..0000000
--- a/tests/00-db-migration-0-to-1-delim-mismatch/local.conf
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace inbox {
- separator = "\""
- location = maildir:~/inbox:LAYOUT=index
- inbox = yes
- list = yes
-}
diff --git a/tests/00-db-migration-0-to-1-delim-mismatch/remote.conf b/tests/00-db-migration-0-to-1-delim-mismatch/remote.conf
deleted file mode 100644
index cc6781d..0000000
--- a/tests/00-db-migration-0-to-1-delim-mismatch/remote.conf
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace inbox {
- separator = ^
- location = maildir:~/inbox:LAYOUT=index
- inbox = yes
- list = yes
-}
diff --git a/tests/00-db-migration-0-to-1-delim-mismatch/run b/tests/00-db-migration-0-to-1-delim-mismatch/run
deleted file mode 100644
index 434c678..0000000
--- a/tests/00-db-migration-0-to-1-delim-mismatch/run
+++ /dev/null
@@ -1,8 +0,0 @@
-# import an existing non-migrated database
-sqlite3 "$XDG_DATA_HOME/interimap/remote.db" <"$TESTDIR/before.sql"
-! interimap
-
-# may happen if the server(s) software or its configuration changed
-xgrep -Fx 'ERROR: Local and remote hierachy delimiters differ (local "\"", remote "^"), refusing to update `mailboxes` table.' <"$STDERR"
-
-# vim: set filetype=sh :
diff --git a/tests/00-db-migration-0-to-1-foreign-key-violation/local.conf b/tests/00-db-migration-0-to-1-foreign-key-violation/local.conf
deleted file mode 100644
index 93497d9..0000000
--- a/tests/00-db-migration-0-to-1-foreign-key-violation/local.conf
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace inbox {
- separator = .
- location = maildir:~/inbox:LAYOUT=index
- inbox = yes
- list = yes
-}
diff --git a/tests/00-db-migration-0-to-1-foreign-key-violation/remote.conf b/tests/00-db-migration-0-to-1-foreign-key-violation/remote.conf
deleted file mode 100644
index 93497d9..0000000
--- a/tests/00-db-migration-0-to-1-foreign-key-violation/remote.conf
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace inbox {
- separator = .
- location = maildir:~/inbox:LAYOUT=index
- inbox = yes
- list = yes
-}
diff --git a/tests/00-db-migration-0-to-1-foreign-key-violation/run b/tests/00-db-migration-0-to-1-foreign-key-violation/run
deleted file mode 100644
index f2d12a9..0000000
--- a/tests/00-db-migration-0-to-1-foreign-key-violation/run
+++ /dev/null
@@ -1,23 +0,0 @@
-# create new schema and add INBOX
-interimap
-xgrep "^Creating new schema in database file " <"$STDERR"
-xgrep -Fx "database: Created mailbox INBOX" <"$STDERR"
-
-# empty table `mailboxes` and revert its schema to version 0
-sqlite3 "$XDG_DATA_HOME/interimap/remote.db" <<-EOF
- PRAGMA foreign_keys = OFF;
- PRAGMA user_version = 0;
- DROP TABLE mailboxes;
- CREATE TABLE mailboxes (
- idx INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
- mailbox TEXT NOT NULL CHECK (mailbox != '') UNIQUE,
- subscribed BOOLEAN NOT NULL
- );
-EOF
-
-# check that migration fails due to broken referential integrity
-! interimap
-xgrep -Fx "Upgrading database version from 0" <"$STDERR"
-xgrep -Fx "database: ERROR: Broken referential integrity! Refusing to commit changes." <"$STDERR"
-
-# vim: set filetype=sh :
diff --git a/tests/00-db-migration-0-to-1/local.conf b/tests/00-db-migration-0-to-1/local.conf
deleted file mode 100644
index 93497d9..0000000
--- a/tests/00-db-migration-0-to-1/local.conf
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace inbox {
- separator = .
- location = maildir:~/inbox:LAYOUT=index
- inbox = yes
- list = yes
-}
diff --git a/tests/00-db-migration-0-to-1/remote.conf b/tests/00-db-migration-0-to-1/remote.conf
deleted file mode 100644
index 93497d9..0000000
--- a/tests/00-db-migration-0-to-1/remote.conf
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace inbox {
- separator = .
- location = maildir:~/inbox:LAYOUT=index
- inbox = yes
- list = yes
-}
diff --git a/tests/01-rename-exists-db/local.conf b/tests/01-rename-exists-db/local.conf
deleted file mode 100644
index 93497d9..0000000
--- a/tests/01-rename-exists-db/local.conf
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace inbox {
- separator = .
- location = maildir:~/inbox:LAYOUT=index
- inbox = yes
- list = yes
-}
diff --git a/tests/01-rename-exists-db/remote.conf b/tests/01-rename-exists-db/remote.conf
deleted file mode 100644
index 61e3d0d..0000000
--- a/tests/01-rename-exists-db/remote.conf
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace inbox {
- separator = "\\"
- location = maildir:~/inbox:LAYOUT=index
- inbox = yes
- list = yes
-}
diff --git a/tests/01-rename-exists-local/local.conf b/tests/01-rename-exists-local/local.conf
deleted file mode 100644
index 93497d9..0000000
--- a/tests/01-rename-exists-local/local.conf
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace inbox {
- separator = .
- location = maildir:~/inbox:LAYOUT=index
- inbox = yes
- list = yes
-}
diff --git a/tests/01-rename-exists-local/remote.conf b/tests/01-rename-exists-local/remote.conf
deleted file mode 100644
index 61e3d0d..0000000
--- a/tests/01-rename-exists-local/remote.conf
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace inbox {
- separator = "\\"
- location = maildir:~/inbox:LAYOUT=index
- inbox = yes
- list = yes
-}
diff --git a/tests/01-rename-exists-remote/local.conf b/tests/01-rename-exists-remote/local.conf
deleted file mode 100644
index 93497d9..0000000
--- a/tests/01-rename-exists-remote/local.conf
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace inbox {
- separator = .
- location = maildir:~/inbox:LAYOUT=index
- inbox = yes
- list = yes
-}
diff --git a/tests/01-rename-exists-remote/remote.conf b/tests/01-rename-exists-remote/remote.conf
deleted file mode 100644
index 61e3d0d..0000000
--- a/tests/01-rename-exists-remote/remote.conf
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace inbox {
- separator = "\\"
- location = maildir:~/inbox:LAYOUT=index
- inbox = yes
- list = yes
-}
diff --git a/tests/01-rename/local.conf b/tests/01-rename/local.conf
deleted file mode 100644
index 93497d9..0000000
--- a/tests/01-rename/local.conf
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace inbox {
- separator = .
- location = maildir:~/inbox:LAYOUT=index
- inbox = yes
- list = yes
-}
diff --git a/tests/01-rename/remote.conf b/tests/01-rename/remote.conf
deleted file mode 100644
index cc6781d..0000000
--- a/tests/01-rename/remote.conf
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace inbox {
- separator = ^
- location = maildir:~/inbox:LAYOUT=index
- inbox = yes
- list = yes
-}
diff --git a/tests/02-delete/local.conf b/tests/02-delete/local.conf
deleted file mode 100644
index 93497d9..0000000
--- a/tests/02-delete/local.conf
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace inbox {
- separator = .
- location = maildir:~/inbox:LAYOUT=index
- inbox = yes
- list = yes
-}
diff --git a/tests/02-delete/remote.conf b/tests/02-delete/remote.conf
deleted file mode 100644
index cc6781d..0000000
--- a/tests/02-delete/remote.conf
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace inbox {
- separator = ^
- location = maildir:~/inbox:LAYOUT=index
- inbox = yes
- list = yes
-}
diff --git a/tests/03-sync-mailbox-list-partial/interimap.conf b/tests/03-sync-mailbox-list-partial/interimap.conf
deleted file mode 100644
index 4970867..0000000
--- a/tests/03-sync-mailbox-list-partial/interimap.conf
+++ /dev/null
@@ -1 +0,0 @@
-list-mailbox = *
diff --git a/tests/03-sync-mailbox-list-partial/local.conf b/tests/03-sync-mailbox-list-partial/local.conf
deleted file mode 100644
index 93497d9..0000000
--- a/tests/03-sync-mailbox-list-partial/local.conf
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace inbox {
- separator = .
- location = maildir:~/inbox:LAYOUT=index
- inbox = yes
- list = yes
-}
diff --git a/tests/03-sync-mailbox-list-partial/remote.conf b/tests/03-sync-mailbox-list-partial/remote.conf
deleted file mode 100644
index 352cdd4..0000000
--- a/tests/03-sync-mailbox-list-partial/remote.conf
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace inbox {
- separator = ~
- location = maildir:~/inbox:LAYOUT=index
- inbox = yes
- list = yes
-}
diff --git a/tests/03-sync-mailbox-list-partial/run b/tests/03-sync-mailbox-list-partial/run
deleted file mode 100644
index 449115d..0000000
--- a/tests/03-sync-mailbox-list-partial/run
+++ /dev/null
@@ -1,57 +0,0 @@
-# try a bunch of invalid 'list-mailbox' values:
-# empty string, missing space between values, unterminated string
-for v in '""' '"f o o""bar"' '"f o o" "bar" "baz\" x'; do
- sed -ri "s/^(list-mailbox\\s*=\\s*).*/\\1${v//\\/\\\\}/" "$XDG_CONFIG_HOME/interimap/config"
- ! interimap
- xgrep -xF "Invalid value for list-mailbox: $v" <"$STDERR"
-done
-
-# create some mailboxes
-doveadm -u "local" mailbox create "foo" "foo bar" "f\\\"o!o.bar" "f.o.o" "bad"
-for m in "foo" "foo bar" "f\\\"o!o.bar" "f.o.o" "bad" "INBOX"; do
- sample_message | deliver -u "local" -- -m "$m"
-done
-
-# restrict 'list-mailbox' to the above minus "bad"
-sed -ri 's/^(list-mailbox\s*=\s*).*/\1foo "foo bar" "f\\\\\\"o\\x21o.*" "f\\0o\\0o"/' \
- "$XDG_CONFIG_HOME/interimap/config"
-
-# run partial sync
-interimap
-check_mailbox_list "foo" "foo bar" "f\\\"o!o.bar" "f.o.o" "INBOX" "f\\\"o!o" "f" "f.o"
-check_mailboxes_status "foo" "foo bar" "f\\\"o!o.bar" "f.o.o"
-
-# check that "bad" isn't in the remote imap server
-! doveadm -u "remote" mailbox status uidvalidity "bad"
-
-# check that "bad" and "INBOX" aren't in the database
-sqlite3 "$XDG_DATA_HOME/interimap/remote.db" >"$TMPDIR/count" <<-EOF
- SELECT COUNT(*)
- FROM mailboxes
- WHERE mailbox = x'$(printf "%s" "bad" | xxd -ps)'
- OR mailbox = x'$(printf "%s" "INBOX" | xxd -ps)'
-EOF
-[ $(< "$TMPDIR/count") -eq 0 ]
-
-
-# run partial sync
-doveadm -u "remote" mailbox create "f\\\"o!o~baz" "f\\\"o!o~bad"
-for m in "f\\\"o!o~baz" "f\\\"o!o~bad"; do
- sample_message | deliver -u "remote" -- -m "$m"
-done
-interimap "f\\\"o!o.baz"
-
-check_mailbox_list "foo" "foo bar" "f\\\"o!o.bar" "f.o.o" "INBOX" "f\\\"o!o" "f" "f.o" "f\\\"o!o.baz"
-check_mailboxes_status "foo" "foo bar" "f\\\"o!o.bar" "f.o.o" "f\\\"o!o.baz"
-
-# check that "bad", "f\\\"o!o.bad" and "INBOX" aren't in the database
-sqlite3 "$XDG_DATA_HOME/interimap/remote.db" >"$TMPDIR/count" <<-EOF
- SELECT COUNT(*)
- FROM mailboxes
- WHERE mailbox = x'$(printf "%s" "bad" | xxd -ps)'
- OR mailbox = x'$(printf "%s" "INBOX" | xxd -ps)'
- OR mailbox = x'$(printf "%s\\0%s" "f\\\"o!o" "bad" | xxd -ps)'
-EOF
-[ $(< "$TMPDIR/count") -eq 0 ]
-
-# vim: set filetype=sh :
diff --git a/tests/03-sync-mailbox-list-ref/local.conf b/tests/03-sync-mailbox-list-ref/local.conf
deleted file mode 100644
index 6eccf43..0000000
--- a/tests/03-sync-mailbox-list-ref/local.conf
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace inbox {
- separator = /
- location = maildir:~/inbox:LAYOUT=index
- inbox = yes
- list = yes
-}
diff --git a/tests/03-sync-mailbox-list-ref/remote.conf b/tests/03-sync-mailbox-list-ref/remote.conf
deleted file mode 100644
index 61e3d0d..0000000
--- a/tests/03-sync-mailbox-list-ref/remote.conf
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace inbox {
- separator = "\\"
- location = maildir:~/inbox:LAYOUT=index
- inbox = yes
- list = yes
-}
diff --git a/tests/03-sync-mailbox-list-ref/run b/tests/03-sync-mailbox-list-ref/run
deleted file mode 100644
index 3ead25d..0000000
--- a/tests/03-sync-mailbox-list-ref/run
+++ /dev/null
@@ -1,28 +0,0 @@
-# Note: implementation-dependent as the reference name is not a level of
-# mailbox hierarchy nor ends with the hierarchy delimiter
-sed -ri 's#^\[local\]$#&\nlist-reference = foo#; s#^\[remote\]$#&\nlist-reference = bar#' \
- "$XDG_CONFIG_HOME/interimap/config"
-
-# create a bunch of mailboxes in and out the respective list # references
-doveadm -u "local" mailbox create "foo" "foobar" "foo/bar/baz" "foo/baz" "bar"
-doveadm -u "remote" mailbox create "foo"
-
-# deliver somemessages to these mailboxes
-for m in "foo" "foobar" "foo/bar/baz" "foo/baz" "bar"; do
- sample_message | deliver -u "local" -- -m "$m"
-done
-sample_message | deliver -u "remote" -- -m "foo"
-
-interimap
-
-# check that the mailbox lists match
-diff -u --label="local/mailboxes" --label="remote/mailboxes" \
- <( doveadm -u "local" mailbox list | sed -n "s/^foo//p" | sort ) \
- <( doveadm -u "remote" mailbox list | sed -n "s/^bar//p" | tr '\\' '/' | sort )
-
-for m in "" "bar" "/bar/baz" "/baz"; do
- blob="x'$(printf "%s" "$m" | tr "/" "\\0" | xxd -c256 -ps)'"
- check_mailbox_status2 "$blob" "foo$m" "remote" "bar${m//\//\\}"
-done
-
-# vim: set filetype=sh :
diff --git a/tests/03-sync-mailbox-list/local.conf b/tests/03-sync-mailbox-list/local.conf
deleted file mode 100644
index 93497d9..0000000
--- a/tests/03-sync-mailbox-list/local.conf
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace inbox {
- separator = .
- location = maildir:~/inbox:LAYOUT=index
- inbox = yes
- list = yes
-}
diff --git a/tests/03-sync-mailbox-list/remote.conf b/tests/03-sync-mailbox-list/remote.conf
deleted file mode 100644
index 352cdd4..0000000
--- a/tests/03-sync-mailbox-list/remote.conf
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace inbox {
- separator = ~
- location = maildir:~/inbox:LAYOUT=index
- inbox = yes
- list = yes
-}
diff --git a/tests/03-sync-mailbox-list/run b/tests/03-sync-mailbox-list/run
deleted file mode 100644
index b506204..0000000
--- a/tests/03-sync-mailbox-list/run
+++ /dev/null
@@ -1,73 +0,0 @@
-# pre-create some mailboxes and susbscribe to some
-# foo: present on both, subscribed to both
-# bar: present on both, subscribed to local only
-# baz: present on both, subscribed to remote only
-# foo.bar: present on local only
-# foo.baz: present on remote only
-doveadm -u "local" mailbox create "foo" "bar" "baz" "foo.bar" "fo!o [b*a%r]"
-doveadm -u "local" mailbox subscribe "foo" "bar"
-doveadm -u "remote" mailbox create "foo" "bar" "baz" "foo~baz" "foo]bar"
-doveadm -u "remote" mailbox subscribe "foo" "baz"
-
-interimap
-xgrep -Fx "local: Subscribe to baz" <"$STDERR"
-xgrep -Fx "remote: Subscribe to bar" <"$STDERR"
-xgrep -Fx "local: Created mailbox foo.baz" <"$STDERR"
-xgrep -Fx "remote: Created mailbox foo~bar" <"$STDERR"
-
-# check syncing
-check_mailbox_list
-check_mailboxes_status "foo" "bar" "baz" "foo.bar" "foo.baz" "INBOX" "fo!o [b*a%r]" "foo]bar"
-check_mailbox_list -s
-
-
-# delete a mailbox one server and verify that synchronization fails as it's still in the database
-doveadm -u "remote" mailbox delete "foo~baz"
-! interimap
-xgrep -Fx 'database: ERROR: Mailbox foo.baz exists. Run `interimap --target=database --delete foo.baz` to delete.' <"$STDERR"
-interimap --target="database" --delete "foo.baz"
-xgrep -Fx 'database: Removed mailbox foo.baz' <"$STDERR"
-interimap # create again
-xgrep -Fx 'database: Created mailbox foo.baz' <"$STDERR"
-xgrep -Fx 'remote: Created mailbox foo~baz' <"$STDERR"
-
-doveadm -u "local" mailbox delete "foo.bar"
-! interimap
-xgrep -Fx 'database: ERROR: Mailbox foo.bar exists. Run `interimap --target=database --delete foo.bar` to delete.' <"$STDERR"
-interimap --target="database" --delete "foo.bar"
-xgrep -Fx 'database: Removed mailbox foo.bar' <"$STDERR"
-interimap
-xgrep -Fx 'database: Created mailbox foo.bar' <"$STDERR"
-xgrep -Fx 'local: Created mailbox foo.bar' <"$STDERR"
-
-check_mailbox_list
-check_mailboxes_status "foo" "bar" "baz" "foo.bar" "foo.baz" "INBOX" "fo!o [b*a%r]" "foo]bar"
-check_mailbox_list -s
-
-
-# (un)subscribe from some mailboxes, including a non-existent one
-doveadm -u "local" mailbox unsubscribe "foo"
-doveadm -u "remote" mailbox unsubscribe "bar"
-doveadm -u "local" mailbox subscribe "foo.bar" "foo.nonexistent" "foo.baz"
-doveadm -u "remote" mailbox subscribe "foo~bar" "bar~nonexistent"
-
-interimap
-xgrep -Fx 'remote: Unsubscribe to foo' <"$STDERR"
-xgrep -Fx 'local: Unsubscribe to bar' <"$STDERR"
-xgrep -Fx 'remote: Subscribe to foo~baz' <"$STDERR"
-check_mailbox_list
-check_mailbox_list -s $(doveadm -u "local" mailbox list) # exclude "foo.nonexistent" and "bar~nonexistent"
-
-# check that "baz", "foo.bar" and "foo.baz" are the only subscribed mailboxes
-sqlite3 "$XDG_DATA_HOME/interimap/remote.db" >"$TMPDIR/count" <<-EOF
- SELECT COUNT(*)
- FROM mailboxes
- WHERE subscribed <> (mailbox IN (
- x'$(printf "%s" "baz" | xxd -ps)',
- x'$(printf "%s\\0%s" "foo" "bar" | xxd -ps)',
- x'$(printf "%s\\0%s" "foo" "baz" | xxd -ps)'
- ))
-EOF
-[ $(< "$TMPDIR/count") -eq 0 ]
-
-# vim: set filetype=sh :
diff --git a/tests/04-resume/local.conf b/tests/04-resume/local.conf
deleted file mode 100644
index 93497d9..0000000
--- a/tests/04-resume/local.conf
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace inbox {
- separator = .
- location = maildir:~/inbox:LAYOUT=index
- inbox = yes
- list = yes
-}
diff --git a/tests/04-resume/remote.conf b/tests/04-resume/remote.conf
deleted file mode 100644
index 352cdd4..0000000
--- a/tests/04-resume/remote.conf
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace inbox {
- separator = ~
- location = maildir:~/inbox:LAYOUT=index
- inbox = yes
- list = yes
-}
diff --git a/tests/05-repair/local.conf b/tests/05-repair/local.conf
deleted file mode 100644
index 93497d9..0000000
--- a/tests/05-repair/local.conf
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace inbox {
- separator = .
- location = maildir:~/inbox:LAYOUT=index
- inbox = yes
- list = yes
-}
diff --git a/tests/05-repair/remote.conf b/tests/05-repair/remote.conf
deleted file mode 100644
index 352cdd4..0000000
--- a/tests/05-repair/remote.conf
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace inbox {
- separator = ~
- location = maildir:~/inbox:LAYOUT=index
- inbox = yes
- list = yes
-}
diff --git a/tests/06-largeint/local.conf b/tests/06-largeint/local.conf
deleted file mode 100644
index 9c838fd..0000000
--- a/tests/06-largeint/local.conf
+++ /dev/null
@@ -1,5 +0,0 @@
-namespace inbox {
- location = maildir:~/inbox:LAYOUT=index
- inbox = yes
- list = yes
-}
diff --git a/tests/06-largeint/remote.conf b/tests/06-largeint/remote.conf
deleted file mode 100644
index 9c838fd..0000000
--- a/tests/06-largeint/remote.conf
+++ /dev/null
@@ -1,5 +0,0 @@
-namespace inbox {
- location = maildir:~/inbox:LAYOUT=index
- inbox = yes
- list = yes
-}
diff --git a/tests/07-sync-live-multi/remote.conf b/tests/07-sync-live-multi/remote.conf
deleted file mode 100644
index 3267182..0000000
--- a/tests/07-sync-live-multi/remote.conf
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace inbox {
- separator = ^
- location = dbox:~/inbox:LAYOUT=index
- inbox = yes
- list = yes
-}
diff --git a/tests/07-sync-live-multi/remote2.conf b/tests/07-sync-live-multi/remote2.conf
deleted file mode 100644
index 062429e..0000000
--- a/tests/07-sync-live-multi/remote2.conf
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace inbox {
- separator = "\\"
- location = dbox:~/inbox:LAYOUT=index
- inbox = yes
- list = yes
-}
diff --git a/tests/07-sync-live-multi/remote3.conf b/tests/07-sync-live-multi/remote3.conf
deleted file mode 100644
index a4b9b1c..0000000
--- a/tests/07-sync-live-multi/remote3.conf
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace inbox {
- separator = "?"
- location = dbox:~/inbox:LAYOUT=index
- inbox = yes
- list = yes
-}
diff --git a/tests/07-sync-live/local.conf b/tests/07-sync-live/local.conf
deleted file mode 100644
index 1333540..0000000
--- a/tests/07-sync-live/local.conf
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace inbox {
- separator = .
- location = dbox:~/inbox:LAYOUT=index
- inbox = yes
- list = yes
-}
diff --git a/tests/07-sync-live/remote.conf b/tests/07-sync-live/remote.conf
deleted file mode 100644
index 3267182..0000000
--- a/tests/07-sync-live/remote.conf
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace inbox {
- separator = ^
- location = dbox:~/inbox:LAYOUT=index
- inbox = yes
- list = yes
-}
diff --git a/tests/db-exclusive-lock/t b/tests/db-exclusive-lock/t
new file mode 100644
index 0000000..88172c9
--- /dev/null
+++ b/tests/db-exclusive-lock/t
@@ -0,0 +1,16 @@
+interimap_init
+
+# start a background process
+interimap --watch=60 &
+trap "ptree_abort $!" EXIT INT TERM
+
+# wait a short while so we have time to lock the database (ugly and racy...)
+sleep .5
+
+# subsequent runs fail as we can't acquire the exclusive lock
+! interimap || error
+
+grep -Fx "DBD::SQLite::db do failed: database is locked at ./interimap line 177." <"$STDERR" \
+ || error "Is \$DBH->do(\"PRAGMA locking_mode = EXCLUSIVE\"); at line 177?"
+
+# vim: set filetype=sh :
diff --git a/tests/db-migration-0-1-foreign-key-violation/t b/tests/db-migration-0-1-foreign-key-violation/t
new file mode 100644
index 0000000..35e5be5
--- /dev/null
+++ b/tests/db-migration-0-1-foreign-key-violation/t
@@ -0,0 +1,21 @@
+interimap_init
+grep -Fx "database: Created mailbox INBOX" <"$STDERR" || error "INBOX missing from DB"
+
+# empty table `mailboxes` and revert its schema to version 0
+sqlite3 "$XDG_DATA_HOME/interimap/remote.db" <<-EOF
+ PRAGMA foreign_keys = OFF;
+ PRAGMA user_version = 0;
+ DROP TABLE mailboxes;
+ CREATE TABLE mailboxes (
+ idx INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
+ mailbox TEXT NOT NULL CHECK (mailbox != '') UNIQUE,
+ subscribed BOOLEAN NOT NULL
+ );
+EOF
+
+# now migration must fail due to broken referential integrity
+! interimap || error
+grep -Fx "Upgrading database version from 0" <"$STDERR" || error "DB upgrade not attempted"
+grep -Fx "database: ERROR: Broken referential integrity! Refusing to commit changes." <"$STDERR" || error "DB upgrade successful despite broken refint"
+
+# vim: set filetype=sh :
diff --git a/tests/db-no-create--watch/t b/tests/db-no-create--watch/t
new file mode 100644
index 0000000..89f1e3e
--- /dev/null
+++ b/tests/db-no-create--watch/t
@@ -0,0 +1,6 @@
+! interimap --watch=60 || error
+
+grep -Ex "DBI connect\(.*\) failed: unable to open database file at \./interimap line 173\." <"$STDERR" || error
+test \! -e "$XDG_DATA_HOME/interimap/remote.db" || error
+
+# vim: set filetype=sh :
diff --git a/tests/db-upgrade-0-1-delim-mismatch/before.sql b/tests/db-upgrade-0-1-delim-mismatch/before.sql
new file mode 120000
index 0000000..6c31715
--- /dev/null
+++ b/tests/db-upgrade-0-1-delim-mismatch/before.sql
@@ -0,0 +1 @@
+../db-upgrade-0-1/before.sql \ No newline at end of file
diff --git a/tests/db-upgrade-0-1-delim-mismatch/local.conf b/tests/db-upgrade-0-1-delim-mismatch/local.conf
new file mode 100644
index 0000000..900c73f
--- /dev/null
+++ b/tests/db-upgrade-0-1-delim-mismatch/local.conf
@@ -0,0 +1,3 @@
+namespace inbox {
+ separator = "\""
+}
diff --git a/tests/db-upgrade-0-1-delim-mismatch/remote.conf b/tests/db-upgrade-0-1-delim-mismatch/remote.conf
new file mode 100644
index 0000000..2d08a24
--- /dev/null
+++ b/tests/db-upgrade-0-1-delim-mismatch/remote.conf
@@ -0,0 +1,3 @@
+namespace inbox {
+ separator = ^
+}
diff --git a/tests/db-upgrade-0-1-delim-mismatch/t b/tests/db-upgrade-0-1-delim-mismatch/t
new file mode 100644
index 0000000..d133437
--- /dev/null
+++ b/tests/db-upgrade-0-1-delim-mismatch/t
@@ -0,0 +1,7 @@
+# import an existing non-migrated database
+sqlite3 "$XDG_DATA_HOME/interimap/remote.db" <"$TESTDIR/before.sql" || error "Couldn't import DB"
+! interimap || error
+
+grep -Fx 'ERROR: Local and remote hierachy delimiters differ (local "\"", remote "^"), refusing to update table `mailboxes`.' <"$STDERR" || error
+
+# vim: set filetype=sh :
diff --git a/tests/00-db-migration-0-to-1/after.sql b/tests/db-upgrade-0-1/after.sql
index 18b0ad7..18b0ad7 100644
--- a/tests/00-db-migration-0-to-1/after.sql
+++ b/tests/db-upgrade-0-1/after.sql
diff --git a/tests/00-db-migration-0-to-1/before.sql b/tests/db-upgrade-0-1/before.sql
index 333a1dc..333a1dc 100644
--- a/tests/00-db-migration-0-to-1/before.sql
+++ b/tests/db-upgrade-0-1/before.sql
diff --git a/tests/db-upgrade-0-1/local.conf b/tests/db-upgrade-0-1/local.conf
new file mode 100644
index 0000000..b56cc70
--- /dev/null
+++ b/tests/db-upgrade-0-1/local.conf
@@ -0,0 +1,3 @@
+namespace inbox {
+ separator = .
+}
diff --git a/tests/db-upgrade-0-1/remote.conf b/tests/db-upgrade-0-1/remote.conf
new file mode 120000
index 0000000..b798ff5
--- /dev/null
+++ b/tests/db-upgrade-0-1/remote.conf
@@ -0,0 +1 @@
+local.conf \ No newline at end of file
diff --git a/tests/00-db-migration-0-to-1/run b/tests/db-upgrade-0-1/t
index 757fe04..088008e 100644
--- a/tests/00-db-migration-0-to-1/run
+++ b/tests/db-upgrade-0-1/t
@@ -1,14 +1,14 @@
-# create some mailboxes
+# create the mailboxes from the database
doveadm -u "local" mailbox create "a.b1.c1" "a.b1.c2" "a.b2.c" "a2"
doveadm -u "remote" mailbox create "a.b1.c1" "a.b1.c2" "a.b2.c" "a2"
# import an existing non-migrated database
-sqlite3 "$XDG_DATA_HOME/interimap/remote.db" <"$TESTDIR/before.sql"
+sqlite3 "$XDG_DATA_HOME/interimap/remote.db" <"$TESTDIR/before.sql" || error "Couldn't import DB"
# migrate
-interimap
+interimap || error "Couldn't upgrade DB"
-xgrep -Fx "Upgrading database version from 0" <"$STDERR"
+grep -Fx "Upgrading database version from 0" <"$STDERR" || error "Couldn't upgrade DB"
check_mailboxes_status "a.b1.c1" "a.b1.c2" "a.b2.c" "a2"
# verify that the new schema is as expected
@@ -28,6 +28,7 @@ EOF
# XXX need 'user_version' PRAGMA in the dump for future migrations
# http://sqlite.1065341.n5.nabble.com/dump-command-and-user-version-td101228.html
diff -u --label="a/dump.sql" --label="b/dump.sql" \
- "$TMPDIR/dump-expected.sql" "$TMPDIR/dump.sql"
+ "$TMPDIR/dump-expected.sql" "$TMPDIR/dump.sql" \
+ || error "DB dumps differ"
# vim: set filetype=sh :
diff --git a/tests/delete/local.conf b/tests/delete/local.conf
new file mode 100644
index 0000000..b56cc70
--- /dev/null
+++ b/tests/delete/local.conf
@@ -0,0 +1,3 @@
+namespace inbox {
+ separator = .
+}
diff --git a/tests/delete/remote.conf b/tests/delete/remote.conf
new file mode 100644
index 0000000..2d08a24
--- /dev/null
+++ b/tests/delete/remote.conf
@@ -0,0 +1,3 @@
+namespace inbox {
+ separator = ^
+}
diff --git a/tests/02-delete/run b/tests/delete/t
index f63c52c..c38d4d3 100644
--- a/tests/02-delete/run
+++ b/tests/delete/t
@@ -4,15 +4,16 @@ for m in "foo.bar" "foo.bar.baz" "INBOX"; do
sample_message | deliver -u "local" -- -m "$m"
done
-interimap
+interimap_init
check_mailbox_list
check_mailboxes_status "foo.bar" "foo.bar.baz" "INBOX"
sqlite3 "$XDG_DATA_HOME/interimap/remote.db" >"$TMPDIR/dump.sql" <<-EOF
.dump
EOF
-# delete non-existent mailbox is a no-op
-interimap --target="local,remote" --target="database" --delete "nonexistent"
+
+step_start "nonexistent source (no-op)"
+interimap --target="local,remote" --target="database" --delete "nonexistent" || error
check_mailbox_list
check_mailboxes_status "foo.bar" "foo.bar.baz" "INBOX"
@@ -20,13 +21,22 @@ sqlite3 "$XDG_DATA_HOME/interimap/remote.db" >"$TMPDIR/dump2.sql" <<-EOF
.dump
EOF
diff -u --label="a/dump.sql" --label="b/dump.sql" \
- "$TMPDIR/dump.sql" "$TMPDIR/dump2.sql"
+ "$TMPDIR/dump.sql" "$TMPDIR/dump2.sql" || error "SQL dumps differ"
+step_done
+
# foo.bar will become \NoSelect in local, per RFC 3501: "It is permitted
# to delete a name that has inferior hierarchical names and does not
# have the \Noselect mailbox name attribute. In this case, all messages
# in that mailbox are removed, and the name will acquire the \Noselect
# mailbox name attribute."
+step_start "mailbox with inferiors"
+sqlite3 "$XDG_DATA_HOME/interimap/remote.db" >"$TMPDIR/mailboxes.sql" <<-EOF
+ SELECT idx, mailbox FROM mailboxes
+ WHERE mailbox != x'$(printf "%s\\0%s" "foo" "bar" | xxd -ps)'
+ ORDER BY idx
+EOF
+
interimap --target="local" --delete "foo.bar"
check_mailbox_list
@@ -35,33 +45,51 @@ check_mailboxes_status "foo.bar.baz" "INBOX"
sqlite3 "$XDG_DATA_HOME/interimap/remote.db" >"$TMPDIR/dump2.sql" <<-EOF
.dump
EOF
-diff -u --label="a/dump.sql" --label="b/dump.sql" "$TMPDIR/dump.sql" "$TMPDIR/dump2.sql"
+diff -u --label="a/dump.sql" --label="b/dump.sql" \
+ "$TMPDIR/dump.sql" "$TMPDIR/dump2.sql" || error "SQL dumps differ"
! doveadm -u "local" mailbox status uidvalidity "foo.bar" # gone
doveadm -u "remote" mailbox status uidvalidity "foo^bar"
-sqlite3 "$XDG_DATA_HOME/interimap/remote.db" >"$TMPDIR/mailboxes.csv" <<-EOF
- SELECT idx, mailbox
- FROM mailboxes
- WHERE mailbox != x'$(printf "%s\\0%s" "foo" "bar" | xxd -ps)'
-EOF
-
-
# now delete from the remote server and the database
interimap --delete "foo.bar"
! doveadm -u "local" mailbox status uidvalidity "foo.bar"
! doveadm -u "remote" mailbox status uidvalidity "foo^bar"
-sqlite3 "$XDG_DATA_HOME/interimap/remote.db" >"$TMPDIR/mailboxes2.csv" <<-EOF
- SELECT idx, mailbox
- FROM mailboxes
- WHERE mailbox != x'$(printf "%s\\0%s" "foo" "bar" | xxd -ps)'
+sqlite3 "$XDG_DATA_HOME/interimap/remote.db" >"$TMPDIR/mailboxes2.sql" <<-EOF
+ SELECT idx, mailbox FROM mailboxes ORDER BY idx
EOF
-diff -u --label="a/mailboxes.csv" --label="b/mailboxes.csv" \
- "$TMPDIR/mailboxes.csv" "$TMPDIR/mailboxes2.csv"
+diff -u --label="a/mailboxes.sql" --label="b/mailboxes.sql" \
+ "$TMPDIR/mailboxes.sql" "$TMPDIR/mailboxes2.sql" || error "SQL dumps differ"
check_mailbox_list
check_mailboxes_status "foo.bar.baz" "INBOX"
+step_done
+
+
+step_start "INBOX (fail)"
+! interimap --delete "InBoX" || error "deleted INBOX"
+grep -Fx "ERROR: INBOX can't be deleted" <"$STDERR" || error
+
+check_mailbox_list
+check_mailboxes_status "foo.bar.baz" "INBOX"
+step_done
+
+
+step_start "\\Noinferiors mailbox"
+interimap --delete "foo.bar.baz"
+
+! doveadm -u "local" mailbox status uidvalidity "foo.bar.baz"
+! doveadm -u "remote" mailbox status uidvalidity "foo^bar^baz"
+
+sqlite3 "$XDG_DATA_HOME/interimap/remote.db" >"$TMPDIR/count" <<-EOF
+ SELECT COUNT(*) FROM mailboxes
+EOF
+[ "$(< "$TMPDIR/count" )" -eq 1 ] || error "Not only INBOX left?"
+
+check_mailbox_list
+check_mailboxes_status "INBOX"
+step_done
# vim: set filetype=sh :
diff --git a/tests/ignore-mailbox/interimap.conf b/tests/ignore-mailbox/interimap.conf
new file mode 100644
index 0000000..6168958
--- /dev/null
+++ b/tests/ignore-mailbox/interimap.conf
@@ -0,0 +1 @@
+ignore-mailbox = ^virtual(?:\x00|$)
diff --git a/tests/ignore-mailbox/local.conf b/tests/ignore-mailbox/local.conf
new file mode 100644
index 0000000..b56cc70
--- /dev/null
+++ b/tests/ignore-mailbox/local.conf
@@ -0,0 +1,3 @@
+namespace inbox {
+ separator = .
+}
diff --git a/tests/ignore-mailbox/remote.conf b/tests/ignore-mailbox/remote.conf
new file mode 100644
index 0000000..2d08a24
--- /dev/null
+++ b/tests/ignore-mailbox/remote.conf
@@ -0,0 +1,3 @@
+namespace inbox {
+ separator = ^
+}
diff --git a/tests/ignore-mailbox/t b/tests/ignore-mailbox/t
new file mode 100644
index 0000000..f90227c
--- /dev/null
+++ b/tests/ignore-mailbox/t
@@ -0,0 +1,62 @@
+doveadm -u "local" mailbox create "foo" -- "-virtual"
+doveadm -u "remote" mailbox create "bar" -- "virtual-"
+
+interimap_init
+check_mailbox_list
+
+sqlite3 "$XDG_DATA_HOME/interimap/remote.db" >"$TMPDIR/mailboxes.sql" <<-EOF
+ SELECT idx, mailbox FROM mailboxes ORDER BY idx
+EOF
+
+for ((i = 0; i < 16; i++)); do
+ u="$(shuf -n1 -e "local" "remote")" # choose target at random
+ m="$(shuf -n1 -e -- "INBOX" "foo" "bar")"
+ sample_message | deliver -u "$u" -- -m "$m"
+done
+
+# create new mailboxes matching 'ignore-mailbox'
+doveadm -u "local" mailbox create "virtual" "virtual.foo"
+doveadm -u "remote" mailbox create "virtual^bar"
+for n in $(seq 1 "$(shuf -n1 -i1-8)"); do
+ sample_message | deliver -u "local" -- -m "virtual"
+ sample_message | deliver -u "local" -- -m "virtual.foo"
+done
+for n in $(seq 1 "$(shuf -n1 -i1-8)"); do
+ sample_message | deliver -u "remote" -- -m "virtual^bar"
+done
+
+
+# no new mailbox should be created
+interimap || error
+
+sqlite3 "$XDG_DATA_HOME/interimap/remote.db" >"$TMPDIR/mailboxes2.sql" <<-EOF
+ SELECT idx, mailbox FROM mailboxes ORDER BY idx
+EOF
+diff -u --label="a/mailboxes.sql" --label="b/mailboxes.sql" \
+ "$TMPDIR/mailboxes.sql" "$TMPDIR/mailboxes2.sql" || error "SQL dumps differ"
+
+check_mailboxes_status "INBOX" "foo" "bar"
+
+# double check the unsubscribed mailboxes weren't copied
+! doveadm -u "remote" mailbox status uidvalidity "virtual" || error
+! doveadm -u "remote" mailbox status uidvalidity "virtual^foo" || error
+! doveadm -u "local" mailbox status uidvalidity "virtual.bar" || error
+
+
+# ignored mailboxes are created when passed to the command line
+interimap "virtual" "virtual.bar" || error
+grep -Fx "database: Created mailbox virtual" <"$STDERR" || error
+grep -Fx "database: Created mailbox virtual.bar" <"$STDERR" || error
+grep -Fx "local: Created mailbox virtual.bar" <"$STDERR" || error
+grep -Fx "remote: Created mailbox virtual" <"$STDERR" || error
+
+sqlite3 "$XDG_DATA_HOME/interimap/remote.db" >"$TMPDIR/mailboxes.sql" <<-EOF
+ SELECT idx, mailbox FROM mailboxes
+ WHERE mailbox != x'$(printf "virtual" | xxd -ps)'
+ AND mailbox != x'$(printf "%s\\0%s" "virtual" "foo" | xxd -ps)'
+ ORDER BY idx
+EOF
+
+check_mailboxes_status "virtual" "virtual.bar" || error
+
+# vim: set filetype=sh :
diff --git a/tests/06-largeint/run b/tests/largeint/t
index b08bcfa..b0877d5 100644
--- a/tests/06-largeint/run
+++ b/tests/largeint/t
@@ -12,13 +12,14 @@ doveadm -u "remote" mailbox update --uid-validity 2147483647 "bar" # 2^31-1
doveadm -u "remote" mailbox update --uid-validity 1 "baz" #
run() {
- local u m
- for u in local remote; do
- for m in "INBOX" "foo" "bar" "baz"; do
- sample_message | deliver -u "$u" -- -m "$m"
- done
+ local u m i
+ for ((i = 0; i < 64; i++)); do
+ u="$(shuf -n1 -e "local" "remote")" # choose target at random
+ m="$(shuf -n1 -e -- "INBOX" "foo" "bar" "baz")"
+ sample_message | deliver -u "$u" -- -m "$m"
done
- interimap
+ interimap || error
+ check_mailbox_list
check_mailbox_status "INBOX" "foo" "bar" "baz"
}
run
diff --git a/tests/list b/tests/list
new file mode 100644
index 0000000..21aa3f4
--- /dev/null
+++ b/tests/list
@@ -0,0 +1,37 @@
+db-no-create--watch `interimap --watch` refuses to create the database
+db-exclusive-lock mutually exclusive DB access
+
+. DB schema upgrade (v0 -> v1)
+ db-upgrade-0-1 migrate
+ # may happen if the server(s) software or its configuration changed
+ db-upgrade-0-1-delim-mismatch abort on hierarchy delimiter mismatch
+ # foreign key checking was broken until v0.5
+ db-migration-0-1-foreign-key-violation abort on foreign key contraint violation
+
+. Mailbox deletion
+ ... delete
+
+. Mailbox renaming
+ rename-exists-db abort if target exists in the DB
+ rename-exists-local abort if target exists locally
+ rename-exists-remote abort if target exists remotely
+ ... rename-simple
+ ... rename-inferiors
+
+# try values beyond the signed integer limit
+largeint Large UIDVALIDITY/UIDNEXT/HIGHESTMODSEQ values
+
+. Mailbox synchronization
+ ... sync-mailbox-list
+ list-reference list-reference
+ list-mailbox list-mailbox = foo "foo bar" "f\\\"o\x21o.*" "f\0o\0o"
+ list-select-opts list-select-opts = SUBSCRIBED
+ ignore-mailbox ignore-mailbox = ^virtual(?:\x00|$)
+
+resume Resume when aborted
+repair --repair
+
+. Live synchronization (60s)
+ sync-live local/remote simulation
+ sync-live-crippled local/remote simulation (crippled remote)
+ sync-live-multi local/remote1+remote2+remote3 simulation (3 local namespaces)
diff --git a/tests/list-mailbox/interimap.conf b/tests/list-mailbox/interimap.conf
new file mode 100644
index 0000000..6702107
--- /dev/null
+++ b/tests/list-mailbox/interimap.conf
@@ -0,0 +1 @@
+list-mailbox = foo "foo bar" "f\\\"o\x21o.*" "f\0o\0o"
diff --git a/tests/list-mailbox/local.conf b/tests/list-mailbox/local.conf
new file mode 100644
index 0000000..b56cc70
--- /dev/null
+++ b/tests/list-mailbox/local.conf
@@ -0,0 +1,3 @@
+namespace inbox {
+ separator = .
+}
diff --git a/tests/list-mailbox/remote.conf b/tests/list-mailbox/remote.conf
new file mode 100644
index 0000000..2d6b9e0
--- /dev/null
+++ b/tests/list-mailbox/remote.conf
@@ -0,0 +1,3 @@
+namespace inbox {
+ separator = ?
+}
diff --git a/tests/list-mailbox/t b/tests/list-mailbox/t
new file mode 100644
index 0000000..e905537
--- /dev/null
+++ b/tests/list-mailbox/t
@@ -0,0 +1,57 @@
+# create and populate some mailboxes locally
+declare -a MAILBOXES=( "foo" "foo bar" "f\\\"o!o.bar" "f.o.o" )
+doveadm -u "local" mailbox create -- "${MAILBOXES[@]}" "foobad" "baz" "INBOX"
+for ((i = 0; i < 32; i++)); do
+ m="$(shuf -n1 -e -- "${MAILBOXES[@]}" "foobad" "baz" "INBOX")"
+ sample_message | deliver -u "local" -- -m "$m"
+done
+
+interimap_init
+for m in "${MAILBOXES[@]}"; do
+ grep -Fx "remote: Created mailbox ${m//./?}" <"$STDERR" || error "${m//./?}"
+ grep -Fx "database: Created mailbox $m" <"$STDERR" || error
+done
+
+# also check inferiors in the list, but exclude "foobad" and "baz"
+check_mailbox_list "${MAILBOXES[@]}" "INBOX" "f\\\"o!o" "f" "f.o"
+check_mailboxes_status "${MAILBOXES[@]}" || error
+
+# double check that "foobad" and "baz" weren't created
+! doveadm -u "remote" mailbox status uidvalidity "foobad" || error
+! doveadm -u "remote" mailbox status uidvalidity "baz" || error
+
+# check that "foobad" and "INBOX" aren't in the database
+sqlite3 "$XDG_DATA_HOME/interimap/remote.db" >"$TMPDIR/count" <<-EOF
+ SELECT COUNT(*)
+ FROM mailboxes
+ WHERE mailbox = x'$(printf "%s" "foobad" | xxd -u -ps)'
+ OR mailbox = x'$(printf "%s" "INBOX" | xxd -u -ps)'
+ OR mailbox = x'$(printf "%s" "baz" | xxd -u -ps)'
+EOF
+[ $(< "$TMPDIR/count") -eq 0 ] || error
+
+
+# mailbox given on the command line overrides list-mailbox
+sample_message | deliver -u "local" -- -m "foobad"
+sample_message | deliver -u "local" -- -m "foo"
+interimap "foobad" || error
+! grep -F "remote(foo): Added 1 UID(s)" <"$STDERR" || error
+check_mailbox_list "foobad"
+check_mailbox_status "foobad"
+
+interimap "foo" || error
+grep -F "remote(foo): Added 1 UID(s)" <"$STDERR" || error
+check_mailbox_status "foo"
+! check_mailbox_list "baz"
+
+
+# finally, try a bunch of invalid 'list-mailbox' values to test the parser:
+# empty string, missing space between values, unterminated string
+for v in '""' '"f o o""bar"' '"f o o" "bar" "baz\" x'; do
+ sed -ri "s/^(list-mailbox\\s*=\\s*).*/\\1${v//\\/\\\\}/" \
+ "$XDG_CONFIG_HOME/interimap/config"
+ ! interimap || error
+ grep -xF "Invalid value for list-mailbox: $v" <"$STDERR"
+done
+
+# vim: set filetype=sh :
diff --git a/tests/list-reference/interimap.local b/tests/list-reference/interimap.local
new file mode 100644
index 0000000..a013813
--- /dev/null
+++ b/tests/list-reference/interimap.local
@@ -0,0 +1 @@
+list-reference = foo/
diff --git a/tests/list-reference/interimap.remote b/tests/list-reference/interimap.remote
new file mode 100644
index 0000000..f34119c
--- /dev/null
+++ b/tests/list-reference/interimap.remote
@@ -0,0 +1 @@
+list-reference = bar\
diff --git a/tests/list-reference/local.conf b/tests/list-reference/local.conf
new file mode 100644
index 0000000..93e4860
--- /dev/null
+++ b/tests/list-reference/local.conf
@@ -0,0 +1,3 @@
+namespace inbox {
+ separator = /
+}
diff --git a/tests/list-reference/remote.conf b/tests/list-reference/remote.conf
new file mode 100644
index 0000000..9657e89
--- /dev/null
+++ b/tests/list-reference/remote.conf
@@ -0,0 +1,3 @@
+namespace inbox {
+ separator = "\\"
+}
diff --git a/tests/list-reference/t b/tests/list-reference/t
new file mode 100644
index 0000000..a2cc9c7
--- /dev/null
+++ b/tests/list-reference/t
@@ -0,0 +1,47 @@
+# create and populate some mailboxes in and out the respective list references
+doveadm -u "local" mailbox create "foo" "foobar" "foo/bar/baz" "foo/baz" "bar" "bar/baz"
+doveadm -u "remote" mailbox create "foo" "foobaz" "foo/baz" "foo\\baz" "bar\\baz" "bar\\!"
+
+populate() {
+ local i
+ for ((i = 0; i < 32; i++)); do
+ m="$(shuf -n1 -e -- "foo" "foobar" "foo/bar/baz" "foo/baz" "bar" "bar/baz")"
+ sample_message | deliver -u "local" -- -m "$m"
+
+ m="$(shuf -n1 -e -- "foo" "foobar" "foo/baz" "foo\\baz" "bar\\baz" "bar\\!")"
+ sample_message | deliver -u "remote" -- -m "$m"
+ done
+}
+populate
+
+interimap_init
+grep -Fx "database: Created mailbox bar/baz" <"$STDERR" || error
+grep -Fx "database: Created mailbox baz" <"$STDERR" || error
+grep -Fx "database: Created mailbox !" <"$STDERR" || error
+grep -Fx "local: Created mailbox foo/!" <"$STDERR" || error
+grep -Fx "remote: Created mailbox bar\\bar\\baz" <"$STDERR" || error
+
+verify() {
+ # check that the mailbox lists match
+ diff -u --label="local/mailboxes" --label="remote/mailboxes" \
+ <( doveadm -u "local" mailbox list | sed -n 's,^foo/,,p' | sort ) \
+ <( doveadm -u "remote" mailbox list | sed -n 's,^bar\\,,p' | tr '\\' '/' | sort ) \
+ || error "mailbox lists differ"
+
+ for m in "bar/baz" "baz" "!"; do
+ blob="x'$(printf "%s" "$m" | tr "/" "\\0" | xxd -c256 -u -ps)'"
+ check_mailbox_status2 "$blob" "foo/$m" "remote" "bar\\${m//\//\\}"
+ done
+}
+verify
+
+# add more messages and re-check
+populate
+interimap || error
+verify
+
+# double check that mailboxes outside references weren't created
+! doveadm -u "local" mailbox status uidvalidity "foobaz" || error
+! doveadm -u "remote" mailbox status uidvalidity "foobar" || error
+
+# vim: set filetype=sh :
diff --git a/tests/list-select-opts/interimap.conf b/tests/list-select-opts/interimap.conf
new file mode 100644
index 0000000..2fa632d
--- /dev/null
+++ b/tests/list-select-opts/interimap.conf
@@ -0,0 +1 @@
+list-select-opts = SUBSCRIBED
diff --git a/tests/list-select-opts/local.conf b/tests/list-select-opts/local.conf
new file mode 100644
index 0000000..b56cc70
--- /dev/null
+++ b/tests/list-select-opts/local.conf
@@ -0,0 +1,3 @@
+namespace inbox {
+ separator = .
+}
diff --git a/tests/list-select-opts/remote.conf b/tests/list-select-opts/remote.conf
new file mode 100644
index 0000000..2d08a24
--- /dev/null
+++ b/tests/list-select-opts/remote.conf
@@ -0,0 +1,3 @@
+namespace inbox {
+ separator = ^
+}
diff --git a/tests/list-select-opts/t b/tests/list-select-opts/t
new file mode 100644
index 0000000..98acb43
--- /dev/null
+++ b/tests/list-select-opts/t
@@ -0,0 +1,56 @@
+doveadm -u "local" mailbox create -s "INBOX" "foo.bar"
+doveadm -u "remote" mailbox create -s "INBOX" "bar"
+
+interimap_init
+check_mailbox_list
+
+sqlite3 "$XDG_DATA_HOME/interimap/remote.db" >"$TMPDIR/mailboxes.sql" <<-EOF
+ SELECT idx, mailbox FROM mailboxes ORDER BY idx
+EOF
+
+for ((i = 0; i < 16; i++)); do
+ u="$(shuf -n1 -e "local" "remote")" # choose target at random
+ m="$(shuf -n1 -e -- "INBOX" "foo.bar" "bar")"
+ sample_message | deliver -u "$u" -- -m "$m"
+done
+
+# create new unsubscribed mailboxes
+doveadm -u "local" mailbox create "foo"
+doveadm -u "remote" mailbox create "baz"
+
+for ((i = 0; i < 8; i++)); do
+ u="$(shuf -n1 -e "local" "remote")" # choose target at random
+ [ u="local" ] && m="foo" || m="baz"
+ sample_message | deliver -u "$u" -- -m "$m"
+done
+
+
+# no new mailbox should be created
+interimap || error
+
+sqlite3 "$XDG_DATA_HOME/interimap/remote.db" >"$TMPDIR/mailboxes2.sql" <<-EOF
+ SELECT idx, mailbox FROM mailboxes ORDER BY idx
+EOF
+diff -u --label="a/mailboxes.sql" --label="b/mailboxes.sql" \
+ "$TMPDIR/mailboxes.sql" "$TMPDIR/mailboxes2.sql" || error "SQL dumps differ"
+
+check_mailboxes_status "INBOX" "foo.bar" "bar"
+
+# double check the unsubscribed mailboxes weren't copied
+! doveadm -u "remote" mailbox status uidvalidity "foo" || error
+! doveadm -u "local" mailbox status uidvalidity "baz" || error
+
+# reconcile when subcribed
+doveadm -u "local" mailbox subscribe "foo"
+doveadm -u "remote" mailbox subscribe "baz"
+
+interimap || error
+grep -Fx "database: Created mailbox foo" <"$STDERR" || error
+grep -Fx "database: Created mailbox baz" <"$STDERR" || error
+grep -Fx "local: Created mailbox baz" <"$STDERR" || error
+grep -Fx "remote: Created mailbox foo" <"$STDERR" || error
+
+check_mailbox_list
+check_mailboxes_status "INBOX" "foo" "foo.bar" "bar" "baz"
+
+# vim: set filetype=sh :
diff --git a/tests/rename-exists-db/local.conf b/tests/rename-exists-db/local.conf
new file mode 100644
index 0000000..b56cc70
--- /dev/null
+++ b/tests/rename-exists-db/local.conf
@@ -0,0 +1,3 @@
+namespace inbox {
+ separator = .
+}
diff --git a/tests/rename-exists-db/remote.conf b/tests/rename-exists-db/remote.conf
new file mode 100644
index 0000000..9657e89
--- /dev/null
+++ b/tests/rename-exists-db/remote.conf
@@ -0,0 +1,3 @@
+namespace inbox {
+ separator = "\\"
+}
diff --git a/tests/01-rename-exists-db/run b/tests/rename-exists-db/t
index aad7c44..cb6cfcd 100644
--- a/tests/01-rename-exists-db/run
+++ b/tests/rename-exists-db/t
@@ -1,14 +1,14 @@
doveadm -u "local" mailbox create "root.from" "root.from.child" "t.o"
doveadm -u "remote" mailbox create "root\\from" "root\\from\\child" "t\\o"
-interimap
+interimap_init
check_mailbox_list
# delete a mailbox on both servers but leave it in the database, then try to use it as target for --rename
doveadm -u "local" mailbox delete "t.o"
doveadm -u "remote" mailbox delete "t\\o"
-! interimap --rename "root.from" "t.o"
-xgrep -Fx 'database: ERROR: Mailbox t.o exists. Run `interimap --target=database --delete t.o` to delete.' <"$STDERR"
+! interimap --rename "root.from" "t.o" || error
+grep -Fx 'database: ERROR: Mailbox t.o exists. Run `interimap --target=database --delete t.o` to delete.' <"$STDERR" || error
# vim: set filetype=sh :
diff --git a/tests/rename-exists-local/local.conf b/tests/rename-exists-local/local.conf
new file mode 100644
index 0000000..b56cc70
--- /dev/null
+++ b/tests/rename-exists-local/local.conf
@@ -0,0 +1,3 @@
+namespace inbox {
+ separator = .
+}
diff --git a/tests/rename-exists-local/remote.conf b/tests/rename-exists-local/remote.conf
new file mode 100644
index 0000000..9657e89
--- /dev/null
+++ b/tests/rename-exists-local/remote.conf
@@ -0,0 +1,3 @@
+namespace inbox {
+ separator = "\\"
+}
diff --git a/tests/01-rename-exists-local/run b/tests/rename-exists-local/t
index d82a0a4..190f49a 100644
--- a/tests/01-rename-exists-local/run
+++ b/tests/rename-exists-local/t
@@ -1,13 +1,13 @@
doveadm -u "local" mailbox create "root.from" "root.from.child" "t.o"
doveadm -u "remote" mailbox create "root\\from" "root\\from\\child"
-interimap
+interimap_init
check_mailbox_list
# delete a mailbox on the remote server, then try to use it as target for --rename
doveadm -u "remote" mailbox delete "t\\o"
-! interimap --rename "root.from" "t.o"
-xgrep -Fx 'local: ERROR: Mailbox t.o exists. Run `interimap --target=local --delete t.o` to delete.' <"$STDERR"
+! interimap --rename "root.from" "t.o" || error
+grep -Fx 'local: ERROR: Mailbox t.o exists. Run `interimap --target=local --delete t.o` to delete.' <"$STDERR" || error
# vim: set filetype=sh :
diff --git a/tests/rename-exists-remote/local.conf b/tests/rename-exists-remote/local.conf
new file mode 100644
index 0000000..b56cc70
--- /dev/null
+++ b/tests/rename-exists-remote/local.conf
@@ -0,0 +1,3 @@
+namespace inbox {
+ separator = .
+}
diff --git a/tests/rename-exists-remote/remote.conf b/tests/rename-exists-remote/remote.conf
new file mode 100644
index 0000000..9657e89
--- /dev/null
+++ b/tests/rename-exists-remote/remote.conf
@@ -0,0 +1,3 @@
+namespace inbox {
+ separator = "\\"
+}
diff --git a/tests/01-rename-exists-remote/run b/tests/rename-exists-remote/t
index 28af1fc..be16a12 100644
--- a/tests/01-rename-exists-remote/run
+++ b/tests/rename-exists-remote/t
@@ -1,13 +1,13 @@
doveadm -u "local" mailbox create "root.from" "root.from.child" "t.o"
doveadm -u "remote" mailbox create "root\\from" "root\\from\\child" "t\\o"
-interimap
+interimap_init
check_mailbox_list
# delete a mailbox on the local server, then try to use it as target for --rename
doveadm -u "local" mailbox delete "t.o"
-! interimap --rename "root.from" "t.o"
-xgrep -Fx 'remote: ERROR: Mailbox t\o exists. Run `interimap --target=remote --delete t.o` to delete.' <"$STDERR"
+! interimap --rename "root.from" "t.o" || error
+grep -Fx 'remote: ERROR: Mailbox t\o exists. Run `interimap --target=remote --delete t.o` to delete.' <"$STDERR" || remote
# vim: set filetype=sh :
diff --git a/tests/rename-inferiors/local.conf b/tests/rename-inferiors/local.conf
new file mode 100644
index 0000000..b56cc70
--- /dev/null
+++ b/tests/rename-inferiors/local.conf
@@ -0,0 +1,3 @@
+namespace inbox {
+ separator = .
+}
diff --git a/tests/rename-inferiors/remote.conf b/tests/rename-inferiors/remote.conf
new file mode 100644
index 0000000..2d08a24
--- /dev/null
+++ b/tests/rename-inferiors/remote.conf
@@ -0,0 +1,3 @@
+namespace inbox {
+ separator = ^
+}
diff --git a/tests/01-rename/run b/tests/rename-inferiors/t
index 6541c5c..9267e6f 100644
--- a/tests/01-rename/run
+++ b/tests/rename-inferiors/t
@@ -8,7 +8,7 @@ for m in "root^sibbling" "root^sibbling^grandchild" "root2" "INBOX"; do
sample_message | deliver -u "remote" -- -m "$m"
done
-interimap
+interimap_init
check_mailboxes_status "root.from" "root.from.child" "root.from.child2" "root.from.child.grandchild" \
"root.sibbling" "root.sibbling.grandchild" "root2" "INBOX"
sqlite3 "$XDG_DATA_HOME/interimap/remote.db" >"$TMPDIR/mailboxes.csv" <<-EOF
@@ -18,26 +18,31 @@ sqlite3 "$XDG_DATA_HOME/interimap/remote.db" >"$TMPDIR/mailboxes.csv" <<-EOF
ORDER BY idx
EOF
-# renaming a non-existent mailbox doesn't yield an error
-interimap --rename "nonexistent" "nonexistent2"
+step_start "non-existent source (no-op)"
+interimap --rename "nonexistent" "root" || error "Renamed non-existent mailbox?"
+check_mailbox_list
+step_done
+
+step_start "\\NonExistent target (fail)"
+! interimap --rename "root2" "root" || error "Didn't abort on ALREADYEXISTS"
+grep -E "^local: ERROR: Couldn't rename mailbox root2: NO \[ALREADYEXISTS\] " <"$STDERR"
check_mailbox_list
+step_done
-# renaming to an existing name yields an error
-! interimap --rename "root2" "root"
-xgrep -E "^local: ERROR: Couldn't rename mailbox root2: NO \[ALREADYEXISTS\] .*" <"$STDERR"
# rename 'root.from' to 'from.root', including inferiors
+step_start "existing source with inferiors"
interimap --rename "root.from" "from.root"
-xgrep -Fx 'local: Renamed mailbox root.from to from.root' <"$STDERR"
-xgrep -Fx 'remote: Renamed mailbox root^from to from^root' <"$STDERR"
-xgrep -Fx 'database: Renamed mailbox root.from to from.root' <"$STDERR"
+grep -Fx 'local: Renamed mailbox root.from to from.root' <"$STDERR"
+grep -Fx 'remote: Renamed mailbox root^from to from^root' <"$STDERR"
+grep -Fx 'database: Renamed mailbox root.from to from.root' <"$STDERR"
check_mailbox_list
check_mailboxes_status "from.root" "from.root.child" "from.root.child2" "from.root.child.grandchild" \
"root.sibbling" "root.sibbling.grandchild" "root2" "INBOX"
before="$(printf "%s\\0%s" "root" "from" | xxd -u -ps)"
-after="$(printf "%s\\0%s" "from" "root" | xxd -ps)"
+after="$(printf "%s\\0%s" "from" "root" | xxd -u -ps)"
sqlite3 "$XDG_DATA_HOME/interimap/remote.db" >"$TMPDIR/mailboxes2.csv" <<-EOF
.mode csv
SELECT idx,
@@ -50,21 +55,24 @@ sqlite3 "$XDG_DATA_HOME/interimap/remote.db" >"$TMPDIR/mailboxes2.csv" <<-EOF
ORDER BY idx
EOF
diff -u --label="a/mailboxes.csv" --label="b/mailboxes.csv" \
- "$TMPDIR/mailboxes.csv" "$TMPDIR/mailboxes2.csv"
+ "$TMPDIR/mailboxes.csv" "$TMPDIR/mailboxes2.csv" \
+ || error "Mailbox list differs"
+step_done
-# Try to rename \NonExistent root and check that its children move
+# rename \NonExistent root and check that its children move
+step_start "\\NonExistent source with inferiors"
interimap --rename "root" "newroot"
-xgrep -Fq 'local: Renamed mailbox root to newroot' <"$STDERR"
-xgrep -Fq 'remote: Renamed mailbox root to newroot' <"$STDERR"
-xgrep -Fq 'database: Renamed mailbox root to newroot' <"$STDERR"
+grep -Fq 'local: Renamed mailbox root to newroot' <"$STDERR"
+grep -Fq 'remote: Renamed mailbox root to newroot' <"$STDERR"
+grep -Fq 'database: Renamed mailbox root to newroot' <"$STDERR"
check_mailbox_list
check_mailboxes_status "from.root" "from.root.child" "from.root.child2" "from.root.child.grandchild" \
"newroot.sibbling" "newroot.sibbling.grandchild" "root2" "INBOX"
before2="$(printf "%s" "root" | xxd -u -ps)"
-after2="$(printf "%s" "newroot" | xxd -ps)"
+after2="$(printf "%s" "newroot" | xxd -u -ps)"
sqlite3 "$XDG_DATA_HOME/interimap/remote.db" >"$TMPDIR/mailboxes3.csv" <<-EOF
.mode csv
SELECT idx,
@@ -79,6 +87,14 @@ sqlite3 "$XDG_DATA_HOME/interimap/remote.db" >"$TMPDIR/mailboxes3.csv" <<-EOF
ORDER BY idx
EOF
diff -u --label="a/mailboxes.csv" --label="b/mailboxes.csv" \
- "$TMPDIR/mailboxes2.csv" "$TMPDIR/mailboxes3.csv"
+ "$TMPDIR/mailboxes2.csv" "$TMPDIR/mailboxes3.csv" \
+ || error "Mailbox list differs"
+step_done
+
+
+interimap
+check_mailbox_list
+check_mailboxes_status "from.root" "from.root.child" "from.root.child2" "from.root.child.grandchild" \
+ "newroot.sibbling" "newroot.sibbling.grandchild" "root2" "INBOX"
# vim: set filetype=sh :
diff --git a/tests/rename-simple/t b/tests/rename-simple/t
new file mode 100644
index 0000000..6ebee9a
--- /dev/null
+++ b/tests/rename-simple/t
@@ -0,0 +1,61 @@
+doveadm -u "local" mailbox create "foo"
+
+sample_message | deliver -u "local" -- -m "INBOX"
+sample_message | deliver -u "remote" -- -m "INBOX"
+sample_message | deliver -u "remote" -- -m "foo"
+
+interimap_init
+
+sqlite3 "$XDG_DATA_HOME/interimap/remote.db" >"$TMPDIR/mailboxes.csv" <<-EOF
+ .mode csv
+ SELECT idx, hex(mailbox)
+ FROM mailboxes
+ ORDER BY idx
+EOF
+
+step_start "non-existent source (no-op)"
+interimap --rename "nonexistent" "bar" || error "Rename non-existent mailbox?"
+check_mailbox_list
+step_done
+
+step_start "existing target (fail)"
+! interimap --rename "nonexistent" "foo" || error "Overwrote target?"
+grep -Fx "local: ERROR: Mailbox foo exists. Run \`interimap --target=local --delete foo\` to delete." <"$STDERR" || error
+check_mailbox_list
+step_done
+
+step_start "INBOX"
+interimap --rename "INBOX" "baz" || error
+check_mailbox_list
+step_done
+
+step_start "\\Noinferiors mailbox"
+interimap --rename "foo" "bar" || error
+check_mailbox_list
+
+sqlite3 "$XDG_DATA_HOME/interimap/remote.db" >"$TMPDIR/mailboxes2.csv" <<-EOF
+ .mode csv
+ SELECT idx,
+ CASE
+ WHEN mailbox = x'$(printf "baz" | xxd -u -ps)'
+ THEN '$(printf "%s" "INBOX" | xxd -u -ps)'
+ WHEN mailbox = x'$(printf "bar" | xxd -u -ps)'
+ THEN '$(printf "%s" "foo" | xxd -u -ps)'
+ ELSE hex(mailbox)
+ END
+ FROM mailboxes
+ ORDER BY idx
+EOF
+diff -u --label="a/mailboxes.csv" --label="b/mailboxes.csv" \
+ "$TMPDIR/mailboxes.csv" "$TMPDIR/mailboxes2.csv" \
+ || error "Mailbox list differs"
+step_done
+
+interimap
+# recreated after renaming
+grep -Fx "database: Created mailbox INBOX" <"$STDERR"
+
+check_mailbox_list
+check_mailboxes_status "INBOX" "bar" "baz"
+
+# vim: set filetype=sh :
diff --git a/tests/repair/local.conf b/tests/repair/local.conf
new file mode 100644
index 0000000..b56cc70
--- /dev/null
+++ b/tests/repair/local.conf
@@ -0,0 +1,3 @@
+namespace inbox {
+ separator = .
+}
diff --git a/tests/repair/remote.conf b/tests/repair/remote.conf
new file mode 100644
index 0000000..1cbbc07
--- /dev/null
+++ b/tests/repair/remote.conf
@@ -0,0 +1,3 @@
+namespace inbox {
+ separator = ~
+}
diff --git a/tests/05-repair/run b/tests/repair/t
index 66f9ce9..6b205ea 100644
--- a/tests/05-repair/run
+++ b/tests/repair/t
@@ -9,7 +9,7 @@ for ((i = 0; i < 64; i++)); do
sample_message | deliver -u "remote" -- -m "baz"
done
-interimap
+interimap_init
check_mailbox_list
check_mailboxes_status "foo.bar" "baz" "INBOX"
@@ -22,7 +22,7 @@ doveadm -u "remote" expunge mailbox "foo~bar" 4,5,7,10
doveadm -u "local" flags add "\\Answered" mailbox "foo.bar" 2,3,5:7,10
doveadm -u "remote" flags add "\\Seen" mailbox "foo~bar" 4,5,7
-# spoof HIGHESTMODSEQ value in the database, to make it look that we recorded the new changes already
+# spoof HIGHESTMODSEQ value in the database to make it look that we recorded the new changes already
spoof() {
local k="$1" v m hex="$(printf "%s\\0%s" "foo" "bar" | xxd -ps)"
shift
@@ -46,7 +46,7 @@ doveadm -u "remote" mailbox status "all" "foo~bar" >"$TMPDIR/foo-bar.status.remo
# verify that without --repair interimap does nothing due to the spoofed HIGHESTMODSEQ values
-interimap "foo.bar"
+interimap "foo.bar" || error
sqlite3 "$XDG_DATA_HOME/interimap/remote.db" >"$TMPDIR/dump2.sql" <<-EOF
.dump
@@ -58,14 +58,14 @@ diff -u --label="a/foo_bar.local" --label="a/foo_bar.local" "$TMPDIR/foo-bar.s
diff -u --label="a/foo_bar.remote" --label="a/foo_bar.remote" "$TMPDIR/foo-bar.status.remote" "$TMPDIR/foo-bar.status2.remote"
-# deliver more messages and spoof UIDNEXT, on one side only
+# deliver more messages and spoof UIDNEXT *on one side only*
sample_message | deliver -u "local" -- -m "foo.bar"
sample_message | deliver -u "remote" -- -m "foo~bar"
spoof UIDNEXT "local"
spoof HIGHESTMODSEQ "local" "remote"
# now repair
-interimap --repair "baz" "foo.bar"
+interimap --repair "baz" "foo.bar" || error
# 6 updates with \Answered (luid 4,8,11:13,16), 2 of which (luid 12,13) vanished from remote
# 3 updates with \Seen (ruid 6,8,10), 1 of which (uid 10) vanished from remote
@@ -82,26 +82,26 @@ xcgrep 5 -E '^local\(foo\.bar\): WARNING: UID [0-9]+ disappeared. Redownloading
# 6-1 (luid 2 <-> ruid 10 is gone from both)
xcgrep 3 -E '^remote\(foo~bar\): WARNING: UID [0-9]+ disappeared. Redownloading local UID [0-9]+\.$' <"$STDERR"
-xgrep -E '^local\(baz\): Removed 24 UID\(s\) ' <"$STDERR"
-xgrep -E '^remote\(baz\): Removed 5 UID\(s\) ' <"$STDERR"
+grep -E '^local\(baz\): Removed 24 UID\(s\) ' <"$STDERR" || error
+grep -E '^remote\(baz\): Removed 5 UID\(s\) ' <"$STDERR" || error
-# pining UIDs here is not very robust...
-xgrep -E '^local\(foo\.bar\): Updated flags \(\\Answered \\Seen\) for UID 16$' <"$STDERR"
-xgrep -E '^local\(foo\.bar\): Updated flags \(\\Seen\) for UID 14$' <"$STDERR"
-xgrep -E '^remote\(foo~bar\): Updated flags \(\\Answered \\Seen\) for UID 8$' <"$STDERR"
-xgrep -E '^remote\(foo~bar\): Updated flags \(\\Answered\) for UID 3,12,16$' <"$STDERR"
+# hardcoding UIDs here is not very robust...
+grep -E '^local\(foo\.bar\): Updated flags \(\\Answered \\Seen\) for UID 16$' <"$STDERR" || error
+grep -E '^local\(foo\.bar\): Updated flags \(\\Seen\) for UID 14$' <"$STDERR" || error
+grep -E '^remote\(foo~bar\): Updated flags \(\\Answered \\Seen\) for UID 8$' <"$STDERR" || error
+grep -E '^remote\(foo~bar\): Updated flags \(\\Answered\) for UID 3,12,16$' <"$STDERR" || error
# luid 17
xcgrep 1 -E '^remote\(foo~bar\): WARNING: No match for modified local UID [0-9]+. Redownloading\.' <"$STDERR"
-xgrep -E '^local\(foo\.bar\): Added 5 UID\(s\) ' <"$STDERR"
-xgrep -E '^remote\(foo~bar\): Added 4 UID\(s\) ' <"$STDERR"
-xgrep -E '^local\(foo\.bar\): Added 1 UID\(s\) ' <"$STDERR" # the new message
+grep -E '^local\(foo\.bar\): Added 5 UID\(s\) ' <"$STDERR" || error
+grep -E '^remote\(foo~bar\): Added 4 UID\(s\) ' <"$STDERR" || error
+grep -E '^local\(foo\.bar\): Added 1 UID\(s\) ' <"$STDERR" || error # the new message
check_mailbox_list
check_mailboxes_status "baz" "foo.bar"
-interimap
+interimap || error
check_mailboxes_status "baz" "foo.bar" "INBOX"
# vim: set filetype=sh :
diff --git a/tests/resume/local.conf b/tests/resume/local.conf
new file mode 100644
index 0000000..b56cc70
--- /dev/null
+++ b/tests/resume/local.conf
@@ -0,0 +1,3 @@
+namespace inbox {
+ separator = .
+}
diff --git a/tests/resume/remote.conf b/tests/resume/remote.conf
new file mode 100644
index 0000000..1cbbc07
--- /dev/null
+++ b/tests/resume/remote.conf
@@ -0,0 +1,3 @@
+namespace inbox {
+ separator = ~
+}
diff --git a/tests/04-resume/run b/tests/resume/t
index 22d66bc..cb0208c 100644
--- a/tests/04-resume/run
+++ b/tests/resume/t
@@ -5,7 +5,7 @@ for ((i = 0; i < 8; i++)); do
sample_message | deliver -u "local" -- -m "foo.bar"
sample_message | deliver -u "local" -- -m "INBOX"
done
-interimap
+interimap_init
check_mailbox_list
check_mailboxes_status "foo" "foo.bar" "baz" "INBOX"
@@ -36,9 +36,9 @@ EOF
doveadm -u "local" mailbox status "all" "foo" >"$TMPDIR/foo.local"
doveadm -u "remote" mailbox status "all" "foo" >"$TMPDIR/foo.remote"
-! interimap
-xgrep -Fx "Resuming interrupted sync for foo" <"$STDERR"
-xgrep -Fx "local(foo): ERROR: UIDVALIDITY changed! ($uidvalidity2 != $uidvalidity) Need to invalidate the UID cache." <"$STDERR"
+! interimap || error
+grep -Fx "Resuming interrupted sync for foo" <"$STDERR"
+grep -Fx "local(foo): ERROR: UIDVALIDITY changed! ($uidvalidity2 != $uidvalidity) Need to invalidate the UID cache." <"$STDERR"
sqlite3 "$XDG_DATA_HOME/interimap/remote.db" >"$TMPDIR/dump2.sql" <<-EOF
.dump
@@ -70,8 +70,8 @@ sample_message | deliver -u "remote" -- -m "foo~bar"
sample_message | deliver -u "local" -- -m "baz"
interimap "foo.bar" "InBoX" "baz" # ignore "foo"
-xgrep -Fx "Resuming interrupted sync for foo.bar" <"$STDERR"
-xgrep -Fx "Resuming interrupted sync for INBOX" <"$STDERR"
+grep -Fx "Resuming interrupted sync for foo.bar" <"$STDERR"
+grep -Fx "Resuming interrupted sync for INBOX" <"$STDERR"
check_mailbox_list
check_mailboxes_status "foo.bar" "INBOX" "baz" # ignore "foo"
diff --git a/tests/run b/tests/run
index ee11757..cb52518 100755
--- a/tests/run
+++ b/tests/run
@@ -22,27 +22,27 @@ set -ue
PATH=/usr/bin:/bin
export PATH
-if [ $# -ne 1 ]; then
- printf "Usage: %s TESTNAME\\n" "$0" >&2
+if [ $# -eq 0 ] || [ $# -gt 2 ]; then
+ printf "Usage: %s TESTFILE [TESTNAME]\\n" "$0" >&2
exit 1
fi
-TEST="${1%/}"
-TEST="${TEST##*/}"
-NAME="${TEST#[0-9]*-}"
-TESTDIR="$(dirname -- "$0")/$TEST"
+TESTDIR="$(dirname -- "$0")/$1"
+TESTNAME="${2-$1}"
if [ ! -d "$TESTDIR" ]; then
printf "ERROR: Not a directory: %s\\n" "$TESTDIR" >&2
exit 1
fi
-ROOTDIR="$(mktemp --tmpdir="${TMPDIR:-/dev/shm}" --directory "$NAME.XXXXXXXXXX")"
+ROOTDIR="$(mktemp --tmpdir="${TMPDIR:-/dev/shm}" --directory "$1.XXXXXXXXXX")"
trap 'rm -rf -- "$ROOTDIR"' EXIT INT TERM
-STDOUT="$ROOTDIR/stdout"
-STDERR="$ROOTDIR/stderr"
+_STDOUT="$ROOTDIR/stdout"
+_STDERR="$ROOTDIR/stderr"
TMPDIR="$ROOTDIR/tmp"
+STDERR="$(mktemp --tmpdir="$ROOTDIR" "stderr.XXXXXXXXXX")"
mkdir -- "$TMPDIR" "$ROOTDIR/home"
+declare -a REMOTES=()
# Set environment for the given user
environ_set() {
@@ -60,24 +60,35 @@ environ_set() {
# Prepare the test harness
prepare() {
declare -a ENVIRON=()
- local src cfg target u home
+ local src cfg target u home n capability
+ if [ -f "$TESTDIR/remotes" ]; then
+ for cfg in $(seq 1 "$(< "$TESTDIR/remotes")"); do
+ REMOTES+=( "remote$cfg" )
+ done
+ else
+ REMOTES+=( "remote" )
+ fi
# copy dovecot config
- for src in "$TESTDIR/local.conf" "$TESTDIR"/remote*.conf; do
- [ -r "$src" ] || continue
- u="${src#"$TESTDIR/"}"
- u="${u%.conf}"
- home="$ROOTDIR/home/$u"
+ for u in "local" "${REMOTES[@]}"; do
+ home="$ROOTDIR/$u/home"
export "HOME_$u"="$home"
- mkdir -pm0755 -- "$home/.local/bin"
mkdir -pm0700 -- "$home/.config/dovecot"
cat >"$home/.config/dovecot/config" <<-EOF
- log_path = /dev/null
- mail_home = $ROOTDIR/home/%u
+ log_path = $HOME_local/mail.log
+ mail_home = $home
+ mail_location = dbox:~/inbox:LAYOUT=index
mailbox_list_index = yes
ssl = no
+ namespace inbox {
+ inbox = yes
+ }
EOF
- cat >>"$home/.config/dovecot/config" <"$src"
+ if [ -f "$TESTDIR/$u.conf" ]; then
+ cat >>"$home/.config/dovecot/config" <"$TESTDIR/$u.conf"
+ fi
+
environ_set "$u"
+ mkdir -pm0755 -- "$home/.local/bin"
cat >"$home/.local/bin/doveadm" <<-EOF
#!/bin/sh
exec env -i ${ENVIRON[@]@Q} \\
@@ -89,36 +100,62 @@ prepare() {
# copy interimap config
mkdir -pm0700 -- "$HOME_local/.local/share/interimap"
mkdir -pm0700 -- "$HOME_local/.config/interimap"
- for cfg in "$TESTDIR"/remote*.conf; do
- cfg="${cfg#"$TESTDIR/remote"}"
- cfg="${cfg%.conf}"
- u="remote$cfg"
+ for u in "${REMOTES[@]}"; do
+ n="${u#remote}"
eval home="\$HOME_$u"
- if [ -f "$TESTDIR/interimap.conf" ]; then
- cat <"$TESTDIR/interimap.conf" >>"$HOME_local/.config/interimap/config$cfg"
- fi
- cat >>"$HOME_local/.config/interimap/config$cfg" <<-EOF
+
+ cat >>"$HOME_local/.config/interimap/config$n" <<-EOF
database = $u.db
-
+ #logfile = $HOME_local/interimap$n.log
+ EOF
+ if [ -f "$TESTDIR/interimap$n.conf" ]; then
+ cat <"$TESTDIR/interimap$n.conf" >>"$HOME_local/.config/interimap/config$n"
+ fi
+
+ cat >>"$HOME_local/.config/interimap/config$n" <<-EOF
+
[local]
type = tunnel
command = exec ${HOME_local@Q}/.local/bin/doveadm exec imap
null-stderr = NO
+ EOF
+ if [ -f "$TESTDIR/interimap$n.local" ]; then
+ cat <"$TESTDIR/interimap$n.local" >>"$HOME_local/.config/interimap/config$n"
+ fi
+
+ # `doveadm exec imap` ignores 'imap_capability' from doveconf/config
+ capability="$(doveconf -c "$home/.config/dovecot/config" -h imap_capability)"
+ cat >>"$HOME_local/.config/interimap/config$n" <<-EOF
[remote]
type = tunnel
- command = exec ${home@Q}/.local/bin/doveadm exec imap
+ command = exec ${home@Q}/.local/bin/doveadm exec imap ${capability:+-oimap_capability=${capability@Q}}
null-stderr = NO
EOF
+ if [ -f "$TESTDIR/interimap$n.remote" ]; then
+ cat <"$TESTDIR/interimap$n.remote" >>"$HOME_local/.config/interimap/config$n"
+ fi
done
}
prepare
# Wrappers for interimap(1) and doveadm(1)
interimap() {
- declare -a ENVIRON=()
+ declare -a ENVIRON=() r=0
environ_set "local"
- env -i "${ENVIRON[@]}" perl -I./lib -T ./interimap "$@"
+ env -i "${ENVIRON[@]}" perl -I./lib -T ./interimap "$@" 2>"$STDERR" || r=$?
+ cat "$STDERR" >&2
+ return $r
+}
+interimap_init() {
+ local u="${1-remote}"
+ local db="$XDG_DATA_HOME/interimap/$u.db"
+ local cfg="config${u#remote}"
+
+ test \! -e "$db" || error "Database already exists" 1
+ interimap --config "$cfg" || error "Couldn't initialize interimap" 1
+ test -f "$db" || error "Database is still missing" 1
+ grep -Fx "Creating new schema in database file $db" <"$STDERR" || error "DB wasn't created" 1
}
doveadm() {
if [ $# -le 2 ] || [ "$1" != "-u" ]; then
@@ -167,9 +204,7 @@ dump_test_result() {
local above="<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"
local src u home
declare -a ENVIRON=()
- for src in "$TESTDIR/local.conf" "$TESTDIR"/remote*.conf; do
- u="${src#"$TESTDIR/"}"
- u="${u%.conf}"
+ for u in "local" "${REMOTES[@]}"; do
environ_set "$u"
eval home="\$HOME_$u"
printf "%s dovecot configuration:\\n%s\\n" "$u" "$below"
@@ -177,16 +212,18 @@ dump_test_result() {
printf "%s\\n\\n" "$above"
done
- printf "(local) interimap configuration:\\n%s\\n" "$below"
- cat <"$HOME_local/.config/interimap/config"
- printf "%s\\n\\n" "$above"
+ for u in "${REMOTES[@]}"; do
+ printf "interimap configuration (local <-> $u):\\n%s\\n" "$below"
+ cat <"$HOME_local/.config/interimap/config${u#remote}"
+ printf "%s\\n\\n" "$above"
+ done
- printf "standard output was:\\n%s\\n" "$below"
- cat <"$STDOUT"
+ printf "standard output:\\n%s\\n" "$below"
+ cat <"$_STDOUT"
printf "%s\\n\\n" "$above"
- printf "standard error was:\\n%s\\n" "$below"
- cat <"$STDERR"
+ printf "standard error:\\n%s\\n" "$below"
+ cat <"$_STDERR"
printf "%s\\n\\n" "$above"
}
@@ -225,7 +262,7 @@ check_mailbox_status2() {
WHERE mailbox = $blob
EOF
)
- check_mailbox_status_values "local" "$lmailbox" $lUIDVALIDITY $lUIDNEXT $lHIGHESTMODSEQ $MESSAGES
+ check_mailbox_status_values "local" "$lmailbox" $lUIDVALIDITY $lUIDNEXT $lHIGHESTMODSEQ $MESSAGES
check_mailbox_status_values "$u" "$rmailbox" $rUIDVALIDITY $rUIDNEXT $rHIGHESTMODSEQ $MESSAGES
local a b
@@ -304,38 +341,54 @@ check_mailbox_list() {
<( printf "%s" "${lmailboxes[*]}" | sort ) <( printf "%s" "${rmailboxes[*]}" | sort )
}
-# Wrappers for grep(1) and `grep -C`
-xgrep() {
- if ! grep -q "$@"; then
- printf "\`grep %s\` failed on line %d\\n" "${*@Q}" ${BASH_LINENO[0]} >&2
- exit 1
- fi
-}
+# Wrapper for `grep -c`
xcgrep() {
local m="$1" n
shift
if ! n="$(grep -c "$@")" || [ $m -ne $n ]; then
- printf "\`grep -c %s\` failed on line %d: %d != %d\\n" "${*@Q}" ${BASH_LINENO[0]} "$m" "$n" >&2
- exit 1
+ error "\`grep -c ${*@Q}\` failed ($m != $n)" 1
fi
}
+error() {
+ local err="${1+": $1"}" i=${2-0}
+ printf "ERROR$err on file %s line %d\\n" "${BASH_SOURCE[i+1]}" ${BASH_LINENO[i]} >&2
+ exit 1
+}
+ptree_abort() {
+ local pid
+ for pid in "$@"; do
+ # kill a process and its children
+ pkill -TERM -P "$pid" || printf "pkill(1) exited with status %d\\n" "$?" >&2
+ kill -TERM "$pid" || printf "kill(1) exited with status %d\\n" "$?" >&2
+ done
+ wait
+}
+step_start() { printf "%s%s..." "${INDENT-}" "$1" >&3; }
+step_done() { passed >&3; }
+failed() {
+ [ -t 1 ] && printf " \\x1B[1;31mFAILED\\x1B[0m\\n" || echo " FAILED"
+}
+passed() {
+ [ -t 1 ] && printf " \\x1B[1;32mPASSED\\x1B[0m\\n" || echo " PASSED"
+}
# Run test in a sub-shell
declare -a ENVIRON=()
environ_set "local"
-export TMPDIR TESTDIR STDOUT STDERR "${ENVIRON[@]}"
+export TMPDIR TESTDIR STDERR "${ENVIRON[@]}"
export -f environ_set doveadm interimap sqlite3 sample_message deliver
+export -f interimap_init ptree_abort step_start step_done passed
export -f check_mailbox_status check_mailbox_status_values check_mailbox_status2
-export -f check_mailboxes_status check_mailbox_list xgrep xcgrep
-printf "%s..." "$TEST"
-if ! bash -ue "$TESTDIR/run" >"$STDOUT" 2>"$STDERR"; then
- echo " FAILED"
- dump_test_result
+export -f check_mailboxes_status check_mailbox_list xcgrep error
+[ "$TESTNAME" = "..." ] || printf "%s%s..." "${INDENT-}" "$TESTNAME"
+if ! bash -ue "$TESTDIR/t" 3>&1 >"$_STDOUT" 2>"$_STDERR"; then
+ failed
+ [ "${QUIET-n}" = "y" ] || dump_test_result
exit 1
else
- echo " OK"
- if grep -Paq "\\x00" -- "$STDOUT" "$STDERR"; then
- printf "\\tWarn: binary output (outstanding \\0)!\\n"
+ [ "$TESTNAME" = "..." ] || passed
+ if grep -Paq "\\x00" -- "$_STDOUT" "$_STDERR"; then
+ printf "\\tWARN: binary output (outstanding \\0)!\\n"
fi
exit 0
fi
diff --git a/tests/run-all b/tests/run-all
new file mode 100755
index 0000000..1eca50c
--- /dev/null
+++ b/tests/run-all
@@ -0,0 +1,65 @@
+#!/bin/bash
+
+#----------------------------------------------------------------------
+# Test suite for InterIMAP
+# Copyright © 2019 Guilhem Moulin <guilhem@fripost.org>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#----------------------------------------------------------------------
+
+set -ue
+PATH=/usr/bin:/bin
+export PATH
+
+BASEDIR="$(dirname -- "$0")"
+RUN="$BASEDIR/run"
+
+failed=0
+
+while IFS="" read -r x; do
+ if [[ "$x" =~ ^([[:blank:]]*)([^[:blank:]#]+)[[:blank:]]+(.*)$ ]]; then
+ indent="${BASH_REMATCH[1]}"
+ t="${BASH_REMATCH[2]}"
+ desc="${BASH_REMATCH[3]}"
+
+ if [ "$t" = "." ]; then
+ printf "%s%s:\\n" "$indent" "$desc"
+ continue
+ elif [ "$t" = "..." ]; then
+ t="$desc"
+ desc="..."
+ fi
+ elif [[ "$x" =~ ^([[:blank:]]*)([^[:blank:]#]+)$ ]]; then
+ indent="${BASH_REMATCH[1]}"
+ t="${BASH_REMATCH[2]}"
+ unset desc
+ else
+ continue
+ fi
+
+ if [ ! -d "$BASEDIR/$t" ]; then
+ printf "WARN: %s does doesn't exist, skipping\\n" "$t" >&2
+ continue
+ fi
+
+ INDENT="$indent" "$RUN" "$t" ${desc+"$desc"} || failed=$(( failed+1 ))
+done <"$BASEDIR/list"
+
+if [ $failed -eq 0 ]; then
+ printf "All tests passed.\\n"
+ exit 0
+else
+ printf "%d test(s) failed.\\n" $failed
+ exit 1
+fi
diff --git a/tests/sync-live-crippled/local.conf b/tests/sync-live-crippled/local.conf
new file mode 120000
index 0000000..ad27dd1
--- /dev/null
+++ b/tests/sync-live-crippled/local.conf
@@ -0,0 +1 @@
+../sync-live/local.conf \ No newline at end of file
diff --git a/tests/sync-live-crippled/remote.conf b/tests/sync-live-crippled/remote.conf
new file mode 100644
index 0000000..76c08e0
--- /dev/null
+++ b/tests/sync-live-crippled/remote.conf
@@ -0,0 +1,6 @@
+namespace inbox {
+ separator = ^
+}
+
+# strict minimum of IMAP capabilities required for interimap to work
+imap_capability = IMAP4rev1 ENABLE UIDPLUS LIST-EXTENDED QRESYNC LIST-STATUS
diff --git a/tests/sync-live-crippled/t b/tests/sync-live-crippled/t
new file mode 120000
index 0000000..189360e
--- /dev/null
+++ b/tests/sync-live-crippled/t
@@ -0,0 +1 @@
+../sync-live/t \ No newline at end of file
diff --git a/tests/sync-live-multi/interimap1.local b/tests/sync-live-multi/interimap1.local
new file mode 100644
index 0000000..a013813
--- /dev/null
+++ b/tests/sync-live-multi/interimap1.local
@@ -0,0 +1 @@
+list-reference = foo/
diff --git a/tests/sync-live-multi/interimap2.local b/tests/sync-live-multi/interimap2.local
new file mode 100644
index 0000000..8f10633
--- /dev/null
+++ b/tests/sync-live-multi/interimap2.local
@@ -0,0 +1 @@
+list-reference = bar/
diff --git a/tests/sync-live-multi/interimap3.local b/tests/sync-live-multi/interimap3.local
new file mode 100644
index 0000000..31dee55
--- /dev/null
+++ b/tests/sync-live-multi/interimap3.local
@@ -0,0 +1 @@
+list-reference = baz/
diff --git a/tests/07-sync-live-multi/local.conf b/tests/sync-live-multi/local.conf
index baae39d..baae39d 100644
--- a/tests/07-sync-live-multi/local.conf
+++ b/tests/sync-live-multi/local.conf
diff --git a/tests/sync-live-multi/remote1.conf b/tests/sync-live-multi/remote1.conf
new file mode 100644
index 0000000..2d08a24
--- /dev/null
+++ b/tests/sync-live-multi/remote1.conf
@@ -0,0 +1,3 @@
+namespace inbox {
+ separator = ^
+}
diff --git a/tests/sync-live-multi/remote2.conf b/tests/sync-live-multi/remote2.conf
new file mode 100644
index 0000000..9657e89
--- /dev/null
+++ b/tests/sync-live-multi/remote2.conf
@@ -0,0 +1,3 @@
+namespace inbox {
+ separator = "\\"
+}
diff --git a/tests/sync-live-multi/remote3.conf b/tests/sync-live-multi/remote3.conf
new file mode 100644
index 0000000..0b6aafd
--- /dev/null
+++ b/tests/sync-live-multi/remote3.conf
@@ -0,0 +1,3 @@
+namespace inbox {
+ separator = "?"
+}
diff --git a/tests/sync-live-multi/remotes b/tests/sync-live-multi/remotes
new file mode 100644
index 0000000..00750ed
--- /dev/null
+++ b/tests/sync-live-multi/remotes
@@ -0,0 +1 @@
+3
diff --git a/tests/07-sync-live-multi/run b/tests/sync-live-multi/t
index 15a27fd..9b129ec 100644
--- a/tests/07-sync-live-multi/run
+++ b/tests/sync-live-multi/t
@@ -1,72 +1,59 @@
-# add references to each interimap instance
-sed -ri 's#^\[local\]$#&\nlist-reference = foo/#' "$XDG_CONFIG_HOME/interimap/config"
-sed -ri 's#^\[local\]$#&\nlist-reference = bar/#' "$XDG_CONFIG_HOME/interimap/config2"
-sed -ri 's#^\[local\]$#&\nlist-reference = baz/#' "$XDG_CONFIG_HOME/interimap/config3"
-
-# create databases
-interimap --config="config"
-interimap --config="config2"
-interimap --config="config3"
-
-# start long-lived interimap processes
-interimap --config="config" --watch=1 & pid=$!
-interimap --config="config2" --watch=1 & pid2=$!
-interimap --config="config3" --watch=1 & pid3=$!
-
-abort() {
- # kill interimap process and its children
- pkill -P "$pid" -TERM || true
- kill -TERM "$pid" || true
- pkill -P "$pid2" -TERM || true
- kill -TERM "$pid2" || true
- pkill -P "$pid3" -TERM || true
- kill -TERM "$pid3" || true
- wait
-}
-trap abort EXIT INT TERM
-
+TIMEOUT=60
# mailbox list (as seen on local) and alphabet
-declare -a mailboxes=( "INBOX" ) alphabet=()
+declare -a MAILBOXES=( "INBOX" ) ALPHABET=()
str="#+-0123456789@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz"
for ((i=0; i < ${#str}; i++)); do
- alphabet[i]="${str:i:1}"
+ ALPHABET[i]="${str:i:1}"
done
-declare -a targets=( "local" "remote" "remote2" "remote3" )
+declare -a TARGETS=( "local" "remote1" "remote2" "remote3" )
+
+
+# create databases
+interimap_init "remote1"
+interimap_init "remote2"
+interimap_init "remote3"
+
+# start long-lived interimap processes
+declare -a PID=()
+trap 'ptree_abort ${PID[@]}' EXIT INT TERM
+interimap --config="config1" --watch=1 & PID+=( $! )
+interimap --config="config2" --watch=1 & PID+=( $! )
+interimap --config="config3" --watch=1 & PID+=( $! )
-timer=$(( $(date +%s) + 30 ))
+timer=$(( $(date +%s) + TIMEOUT ))
while [ $(date +%s) -le $timer ]; do
# create new mailbox with 10% probability
if [ $(shuf -n1 -i0-9) -eq 0 ]; then
- u="$(shuf -n1 -e -- "${targets[@]}")" # choose target at random
+ u="$(shuf -n1 -e -- "${TARGETS[@]}")" # choose target at random
case "$u" in
local) ns="$(shuf -n1 -e "foo/" "bar/" "baz/")";;
- remote) ns="foo/";;
+ remote1) ns="foo/";;
remote2) ns="bar/";;
remote3) ns="baz/";;
- *) echo "Uh?" >&2; exit 1;;
+ *) error "Uh?";;
esac
m=
d=$(shuf -n1 -i1-3) # random depth
for (( i=0; i < d; i++)); do
l=$(shuf -n1 -i1-16)
- m="${m:+$m/}$(shuf -n "$l" -e -- "${alphabet[@]}" | tr -d '\n')"
+ m="${m:+$m/}$(shuf -n "$l" -e -- "${ALPHABET[@]}" | tr -d '\n')"
done
- mailboxes+=( "$ns$m" )
+ MAILBOXES+=( "$ns$m" )
case "$u" in
local) m="$ns$m";;
- remote) m="${m//\//^}";;
+ remote1) m="${m//\//^}";;
remote2) m="${m//\//\\}";;
remote3) m="${m//\//\?}";;
- *) echo "Uh?" >&2; exit 1;;
+ *) error "Uh?";;
esac
doveadm -u "$u" mailbox create -- "$m"
fi
# EXPUNGE some messages
- u="$(shuf -n1 -e -- "${targets[@]}")" # choose target at random
+ u="$(shuf -n1 -e -- "${TARGETS[@]}")" # choose target at random
n="$(shuf -n1 -i0-3)"
while read guid uid; do
doveadm -u "$u" expunge mailbox-guid "$guid" uid "$uid"
@@ -74,7 +61,7 @@ while [ $(date +%s) -le $timer ]; do
# mark some existing messages as read (toggle \Seen flag as unlike other
# flags it's easier to query and check_mailboxes_status checks it)
- u="$(shuf -n1 -e -- "${targets[@]}")" # choose target at random
+ u="$(shuf -n1 -e -- "${TARGETS[@]}")" # choose target at random
n="$(shuf -n1 -i0-9)"
while read guid uid; do
a="$(shuf -n1 -e add remove replace)"
@@ -83,14 +70,14 @@ while [ $(date +%s) -le $timer ]; do
# select at random a mailbox where to deliver some messages
u="$(shuf -n1 -e "local" "remote")" # choose target at random
- m="$(shuf -n1 -e -- "${mailboxes[@]}")"
+ m="$(shuf -n1 -e -- "${MAILBOXES[@]}")"
if [ "$u" = "remote" ]; then
case "$m" in
- foo/*) u="remote"; m="${m#foo/}"; m="${m//\//^}";;
+ foo/*) u="remote1"; m="${m#foo/}"; m="${m//\//^}";;
bar/*) u="remote2"; m="${m#bar/}"; m="${m//\//\\}";;
baz/*) u="remote3"; m="${m#baz/}"; m="${m//\//\?}";;
- INBOX) u="$(shuf -n1 -e "remote" "remote2" "remote3")";;
- *) echo "Uh? $m" >&2; exit 1;;
+ INBOX) u="$(shuf -n1 -e "remote1" "remote2" "remote3")";;
+ *) error "Uh? $m";;
esac
fi
@@ -100,8 +87,10 @@ while [ $(date +%s) -le $timer ]; do
sample_message | deliver -u "$u" -- -m "$m"
done
- # sleep a little bit
- sleep "$(printf "0.%03d" "$(shuf -n1 -i1-999)")"
+ # sleep a little bit (sometimes beyond --watch timer, sometimes not)
+ s=$(shuf -n1 -i1-1500)
+ [ $s -ge 1000 ] && s="$(printf "1.%03d" $((s-1000)))" || s="$(printf "0.%03d" $s)"
+ sleep "$s"
done
# wait a little longer so interimap has time to run loop() again and
@@ -109,13 +98,13 @@ done
# started above
sleep 2
-abort
+ptree_abort ${PID[@]}
trap - EXIT INT TERM
# check that the mailbox lists match
-diff -u --label="local/mailboxes" --label="remote/mailboxes" \
- <( doveadm -u "local" mailbox list | sed -n "s,^foo/,,p" | sort ) \
- <( doveadm -u "remote" mailbox list | tr '^' '/' | sort )
+diff -u --label="local/mailboxes" --label="remote1/mailboxes" \
+ <( doveadm -u "local" mailbox list | sed -n "s,^foo/,,p" | sort ) \
+ <( doveadm -u "remote1" mailbox list | tr '^' '/' | sort )
diff -u --label="local/mailboxes" --label="remote2/mailboxes" \
<( doveadm -u "local" mailbox list | sed -n "s,^bar/,,p" | sort ) \
<( doveadm -u "remote2" mailbox list | tr '\\' '/' | sort )
@@ -123,13 +112,13 @@ diff -u --label="local/mailboxes" --label="remote3/mailboxes" \
<( doveadm -u "local" mailbox list | sed -n "s,^baz/,,p" | sort ) \
<( doveadm -u "remote3" mailbox list | tr '?' '/' | sort )
-for m in "${mailboxes[@]}"; do
+for m in "${MAILBOXES[@]}"; do
case "$m" in
- foo/*) u="remote"; mb="${m#foo/}"; mr="${mb//\//^}";;
+ foo/*) u="remote1"; mb="${m#foo/}"; mr="${mb//\//^}";;
bar/*) u="remote2"; mb="${m#bar/}"; mr="${mb//\//\\}";;
baz/*) u="remote3"; mb="${m#baz/}"; mr="${mb//\//\?}";;
INBOX) continue;;
- *) echo "Uh? $m" >&2; exit 1;;
+ *) error "Uh? $m";;
esac
blob="x'$(printf "%s" "$mb" | tr "/" "\\0" | xxd -c256 -ps)'"
check_mailbox_status2 "$blob" "$m" "$u" "$mr"
diff --git a/tests/sync-live/local.conf b/tests/sync-live/local.conf
new file mode 100644
index 0000000..b56cc70
--- /dev/null
+++ b/tests/sync-live/local.conf
@@ -0,0 +1,3 @@
+namespace inbox {
+ separator = .
+}
diff --git a/tests/sync-live/remote.conf b/tests/sync-live/remote.conf
new file mode 100644
index 0000000..2d08a24
--- /dev/null
+++ b/tests/sync-live/remote.conf
@@ -0,0 +1,3 @@
+namespace inbox {
+ separator = ^
+}
diff --git a/tests/07-sync-live/run b/tests/sync-live/t
index 04d8247..19d1e08 100644
--- a/tests/07-sync-live/run
+++ b/tests/sync-live/t
@@ -1,25 +1,19 @@
-# create database
-interimap
-
-# start a long-lived interimap process
-interimap --watch=1 & pid=$!
-
-abort() {
- # kill interimap process and its children
- pkill -P "$pid" -TERM || true
- kill -TERM "$pid" || true
- wait
-}
-trap abort EXIT INT TERM
+TIMEOUT=60
# mailbox list and alphabet (exclude &, / and ~, which dovecot treats specially)
-declare -a mailboxes=( "INBOX" ) alphabet=()
+declare -a MAILBOXES=( "INBOX" ) ALPHABET=()
str="!\"#\$'()+,-0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ\[\\\]_\`abcdefghijklmnopqrstuvwxyz{|}"
for ((i=0; i < ${#str}; i++)); do
- alphabet[i]="${str:i:1}"
+ ALPHABET[i]="${str:i:1}"
done
-timer=$(( $(date +%s) + 30 ))
+interimap_init
+
+# start a long-lived interimap process
+interimap --watch=1 & PID=$!
+trap "ptree_abort $PID" EXIT INT TERM
+
+timer=$(( $(date +%s) + TIMEOUT ))
while [ $(date +%s) -le $timer ]; do
# create new mailbox with 10% probability
if [ $(shuf -n1 -i0-9) -eq 0 ]; then
@@ -27,9 +21,9 @@ while [ $(date +%s) -le $timer ]; do
d=$(shuf -n1 -i1-3) # random depth
for (( i=0; i < d; i++)); do
l=$(shuf -n1 -i1-16)
- m="${m:+$m.}$(shuf -n "$l" -e -- "${alphabet[@]}" | tr -d '\n')"
+ m="${m:+$m.}$(shuf -n "$l" -e -- "${ALPHABET[@]}" | tr -d '\n')"
done
- mailboxes+=( "$m" )
+ MAILBOXES+=( "$m" )
u="$(shuf -n1 -e "local" "remote")" # choose target at random
[ "$u" = "local" ] || m="${m//./^}"
doveadm -u "$u" mailbox create -- "$m"
@@ -53,7 +47,7 @@ while [ $(date +%s) -le $timer ]; do
# select at random a mailbox where to deliver some messages
u="$(shuf -n1 -e "local" "remote")" # choose target at random
- m="$(shuf -n1 -e -- "${mailboxes[@]}")"
+ m="$(shuf -n1 -e -- "${MAILBOXES[@]}")"
[ "$u" = "local" ] || m="${m//./^}"
# deliver between 1 and 5 messages to the chosen mailbox
@@ -62,8 +56,10 @@ while [ $(date +%s) -le $timer ]; do
sample_message | deliver -u "$u" -- -m "$m"
done
- # sleep a little bit
- sleep "$(printf "0.%03d" "$(shuf -n1 -i1-999)")"
+ # sleep a little bit (sometimes beyond --watch timer, sometimes not)
+ s=$(shuf -n1 -i1-1500)
+ [ $s -ge 1000 ] && s="$(printf "1.%03d" $((s-1000)))" || s="$(printf "0.%03d" $s)"
+ sleep "$s"
done
# wait a little longer so interimap has time to run loop() again and
@@ -71,10 +67,10 @@ done
# above
sleep 2
-abort
+ptree_abort $PID
trap - EXIT INT TERM
check_mailbox_list
-check_mailboxes_status "${mailboxes[@]}"
+check_mailboxes_status "${MAILBOXES[@]}"
# vim: set filetype=sh :
diff --git a/tests/sync-mailbox-list/local.conf b/tests/sync-mailbox-list/local.conf
new file mode 100644
index 0000000..b56cc70
--- /dev/null
+++ b/tests/sync-mailbox-list/local.conf
@@ -0,0 +1,3 @@
+namespace inbox {
+ separator = .
+}
diff --git a/tests/sync-mailbox-list/remote.conf b/tests/sync-mailbox-list/remote.conf
new file mode 100644
index 0000000..1cbbc07
--- /dev/null
+++ b/tests/sync-mailbox-list/remote.conf
@@ -0,0 +1,3 @@
+namespace inbox {
+ separator = ~
+}
diff --git a/tests/sync-mailbox-list/t b/tests/sync-mailbox-list/t
new file mode 100644
index 0000000..ea80fbf
--- /dev/null
+++ b/tests/sync-mailbox-list/t
@@ -0,0 +1,93 @@
+# pre-create some mailboxes and susbscribe to some
+# foo: present on both, subscribed to both
+# bar: present on both, subscribed to local only
+# baz: present on both, subscribed to remote only
+# foo.bar: present on local only
+# foo.baz: present on remote only
+doveadm -u "local" mailbox create "foo" "bar" "baz" "foo.bar" "fo!o [b*a%r]"
+doveadm -u "local" mailbox subscribe "foo" "bar"
+doveadm -u "remote" mailbox create "foo" "bar" "baz" "foo~baz" "foo]bar"
+doveadm -u "remote" mailbox subscribe "foo" "baz"
+
+populate() {
+ local i
+ for ((i = 0; i < 32; i++)); do
+ m="$(shuf -n1 -e -- "foo" "bar" "baz" "foo.bar" "fo!o [b*a%r]")"
+ sample_message | deliver -u "local" -- -m "$m"
+
+ m="$(shuf -n1 -e -- "foo" "bar" "baz" "foo~baz" "foo]bar")"
+ sample_message | deliver -u "remote" -- -m "$m"
+ done
+}
+verify() {
+ check_mailbox_list || error
+ check_mailboxes_status "foo" "bar" "baz" "foo.bar" "foo.baz" "INBOX" "fo!o [b*a%r]" "foo]bar"
+}
+populate
+
+step_start "pre-subscribtions"
+interimap_init
+grep -Fx "local: Subscribe to baz" <"$STDERR" || error
+grep -Fx "remote: Subscribe to bar" <"$STDERR" || error
+grep -Fx "local: Created mailbox foo.baz" <"$STDERR" || error
+grep -Fx "remote: Created mailbox foo~bar" <"$STDERR" || error
+step_done
+
+# ensure the mailbox list is synchronized
+step_start "mailbox list and content"
+verify
+check_mailbox_list -s
+step_done
+
+
+# delete a mailbox on one server and verify that synchronization fails as it's still in the database
+step_start "aborts if present in database"
+for u in "local" "remote"; do
+ [ "$u" = "local" ] && { m="foo.bar"; m2="$m"; } || { m="foo.baz"; m2="foo~baz"; }
+
+ doveadm -u "$u" mailbox delete "$m2"
+ ! interimap || error
+ grep -Fx "database: ERROR: Mailbox $m exists. Run \`interimap --target=database --delete $m\` to delete." <"$STDERR"
+
+ interimap --target="database" --delete "$m" || error
+ grep -Fx "database: Removed mailbox $m" <"$STDERR" || error
+
+ interimap || error # create again
+ grep -Fx "database: Created mailbox $m" <"$STDERR" || error
+ grep -Fx "$u: Created mailbox $m2" <"$STDERR" || error
+done
+verify
+check_mailbox_list -s
+step_done
+
+
+
+# (un)subscribe from some mailboxes, including a non-existent one
+step_start "new (un)subscribtions"
+doveadm -u "local" mailbox unsubscribe "foo"
+doveadm -u "remote" mailbox unsubscribe "bar"
+doveadm -u "local" mailbox subscribe "foo.bar" "foo.nonexistent" "foo.baz"
+doveadm -u "remote" mailbox subscribe "foo~bar" "bar~nonexistent"
+populate
+
+interimap
+grep -Fx "remote: Unsubscribe to foo" <"$STDERR"
+grep -Fx "local: Unsubscribe to bar" <"$STDERR"
+grep -Fx "remote: Subscribe to foo~baz" <"$STDERR"
+verify
+check_mailbox_list -s $(doveadm -u "local" mailbox list) # exclude "foo.nonexistent" and "bar~nonexistent"
+
+# check that "baz", "foo.bar" and "foo.baz" are the only subscribed mailboxes
+sqlite3 "$XDG_DATA_HOME/interimap/remote.db" >"$TMPDIR/count" <<-EOF
+ SELECT COUNT(*)
+ FROM mailboxes
+ WHERE subscribed <> (mailbox IN (
+ x'$(printf "%s" "baz" | xxd -ps)',
+ x'$(printf "%s\\0%s" "foo" "bar" | xxd -ps)',
+ x'$(printf "%s\\0%s" "foo" "baz" | xxd -ps)'
+ ))
+EOF
+[ $(< "$TMPDIR/count") -eq 0 ] || error
+step_done
+
+# vim: set filetype=sh :