aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xpullimap5
-rw-r--r--tests/list3
l---------tests/pullimap/interimap.remote1
-rw-r--r--tests/pullimap/local.conf1
-rw-r--r--tests/pullimap/pullimap.conf1
l---------tests/pullimap/remote.conf1
-rw-r--r--tests/pullimap/t96
-rwxr-xr-xtests/run38
-rw-r--r--tests/snippets/dovecot/lmtpd.conf7
9 files changed, 136 insertions, 17 deletions
diff --git a/pullimap b/pullimap
index 3d1a0ec..1dc4b9e 100755
--- a/pullimap
+++ b/pullimap
@@ -29,7 +29,7 @@ use Errno 'EINTR';
use Fcntl qw/O_CREAT O_RDWR O_DSYNC F_SETLK F_WRLCK SEEK_SET F_GETFD F_SETFD FD_CLOEXEC/;
use Getopt::Long qw/:config posix_default no_ignore_case gnu_getopt auto_version/;
use List::Util 'first';
-use Socket qw/PF_INET PF_INET6 SOCK_STREAM/;
+use Socket qw/PF_INET PF_INET6 SOCK_STREAM IPPROTO_TCP/;
use lib 'lib';
use Net::IMAP::InterIMAP 0.0.5 qw/xdg_basedir read_config compact_set/;
@@ -146,8 +146,7 @@ sub sendmail($$) {
: $fam == PF_INET6 ? Socket::pack_sockaddr_in6($port, $addr)
: die;
- my $proto = getprotobyname("tcp") // die;
- socket($SMTP, $fam, SOCK_STREAM, $proto) or die "socket: $!";
+ socket($SMTP, $fam, SOCK_STREAM, IPPROTO_TCP) or die "socket: $!";
until (connect($SMTP, $sockaddr)) {
next if $! == EINTR; # try again if connect(2) was interrupted by a signal
die "connect: $!";
diff --git a/tests/list b/tests/list
index a18cb29..52417c1 100644
--- a/tests/list
+++ b/tests/list
@@ -55,3 +55,6 @@ split-set Split large sets to avoid extra-long command lines
sync-live-crippled local/remote simulation (crippled remote)
sync-live-tls local/remote simulation (TLS remote)
sync-live-multi local/remote1+remote2+remote3 simulation (3 local namespaces)
+
+. pullimap
+ ... pullimap
diff --git a/tests/pullimap/interimap.remote b/tests/pullimap/interimap.remote
new file mode 120000
index 0000000..daf3741
--- /dev/null
+++ b/tests/pullimap/interimap.remote
@@ -0,0 +1 @@
+../tls/interimap.remote \ No newline at end of file
diff --git a/tests/pullimap/local.conf b/tests/pullimap/local.conf
new file mode 100644
index 0000000..b67641f
--- /dev/null
+++ b/tests/pullimap/local.conf
@@ -0,0 +1 @@
+!include conf.d/lmtpd.conf
diff --git a/tests/pullimap/pullimap.conf b/tests/pullimap/pullimap.conf
new file mode 100644
index 0000000..3f6c2e1
--- /dev/null
+++ b/tests/pullimap/pullimap.conf
@@ -0,0 +1 @@
+deliver-method = lmtp:[127.0.0.1]:10024
diff --git a/tests/pullimap/remote.conf b/tests/pullimap/remote.conf
new file mode 120000
index 0000000..6029749
--- /dev/null
+++ b/tests/pullimap/remote.conf
@@ -0,0 +1 @@
+../tls/remote.conf \ No newline at end of file
diff --git a/tests/pullimap/t b/tests/pullimap/t
new file mode 100644
index 0000000..7ae0c5f
--- /dev/null
+++ b/tests/pullimap/t
@@ -0,0 +1,96 @@
+MAILBOX="INBOX"
+TIMEOUT=60
+N=2048
+
+step_start "\`pullimap --idle\` refuses to create the state file"
+! pullimap --idle "remote" || error
+step_done
+
+# make sure remote UIDs are 11-bytes long
+doveadm -u "remote" mailbox update --min-next-uid 1000000000 "$MAILBOX"
+
+# compare mailboxes; can't compare the RFC 3501 TEXT as LMTP adds a
+# Received: header.
+# TODO unset lmtp_add_received_header once avaisable in Sid:
+# https://doc.dovecot.org/settings/dovecot_core_settings/#lmtp-add-received-header
+list_mails_sha256() {
+ local u="$1" guid uid
+ while read guid uid; do
+ doveadm -u "$u" -f "flow" fetch body mailbox-guid "$guid" uid "$uid" \
+ | sed "1s/body=//" | sha256sum
+ done < <(doveadm -u "$u" search mailbox "$MAILBOX") | sort -f
+}
+check() {
+ diff -u --label="local/mails" --label="remote/mails" \
+ <( list_mails_sha256 "local" ) \
+ <( list_mails_sha256 "remote" ) \
+ || error "mailboxes differ"
+}
+
+
+# Add some messages and sync
+step_start "Fetching messages"
+for ((i = 0; i < 32; i++)); do
+ sample_message | deliver -u "remote" -- -m "$MAILBOX"
+done
+
+pullimap "remote" || error
+check
+
+# same thing, but with some missing messages
+for ((i = 0; i < N; i+=2)); do
+ sample_message | deliver -u "remote" -- -m "$MAILBOX"
+ deliver -u "remote" -- -m "$MAILBOX" </dev/null # even seqnum
+done
+for ((i = 0; i < N; i+=2)); do
+ # expunge every other message
+ doveadm -u "remote" expunge mailbox "$MAILBOX" $((N-i+32))
+ sample_message | deliver -u "remote" -- -m "$MAILBOX"
+done
+
+pullimap "remote" || error
+check
+
+# count unseen remote messages
+doveadm -u "remote" search mailbox "$MAILBOX" unseen >"$TMPDIR/unseen"
+[ ! -s "$TMPDIR/unseen" ] || error "\\Unseen messages left"
+step_done
+
+
+step_start "--idle (${TIMEOUT}s)"
+
+pullimap --idle "remote" & PID=$!
+trap "ptree_abort $PID" EXIT INT TERM
+
+timer=$(( $(date +%s) + TIMEOUT ))
+while [ $(date +%s) -le $timer ]; do
+ n="$(shuf -n1 -i1-5)"
+ for (( i=0; i < n; i++)); do
+ sample_message | deliver -u "remote" -- -m "$MAILBOX"
+ done
+
+ s=$(shuf -n1 -i1-1500)
+ [ $s -ge 1000 ] && s="$(printf "1.%03d" $((s-1000)))" || s="$(printf "0.%03d" $s)"
+ sleep "$s"
+done
+
+sleep 2
+ptree_abort $PID
+trap - EXIT INT TERM
+
+check
+step_done
+
+
+step_start "Purging"
+echo "purge-after = 0" >>"$XDG_CONFIG_HOME/pullimap/config"
+for ((i = 0; i < 32; i++)); do
+ sample_message | deliver -u "remote" -- -m "$MAILBOX"
+done
+pullimap "remote"
+
+doveadm -u "remote" search mailbox "$MAILBOX" all >"$TMPDIR/messages"
+[ ! -s "$TMPDIR/messages" ] || error "messages left"
+step_done
+
+# vim: set filetype=sh :
diff --git a/tests/run b/tests/run
index 2903938..30d20f9 100755
--- a/tests/run
+++ b/tests/run
@@ -146,9 +146,10 @@ prepare() {
chmod +x -- "$home/.local/bin/doveadm"
done
- # copy interimap config
- mkdir -pm0700 -- "$HOME_local/.local/share/interimap"
- mkdir -pm0700 -- "$HOME_local/.config/interimap"
+ # copy interimap and pullimap configuration
+ mkdir -pm0700 -- "$HOME_local/.local/share/interimap" "$HOME_local/.local/share/pullimap"
+ mkdir -pm0700 -- "$HOME_local/.config/interimap" "$HOME_local/.config/pullimap"
+ echo "deliver-rcpt = local" >>"$HOME_local/.config/pullimap/config"
for u in "${REMOTES[@]}"; do
n="${u#remote}"
eval home="\$HOME_$u"
@@ -160,6 +161,9 @@ prepare() {
if [ -f "$TESTDIR/interimap$n.conf" ] || [ -L "$TESTDIR/interimap$n.conf" ]; then
cat <"$TESTDIR/interimap$n.conf" >>"$HOME_local/.config/interimap/config$n"
fi
+ if [ -f "$TESTDIR/pullimap.conf" ] || [ -L "$TESTDIR/pullimap.conf" ]; then
+ cat <"$TESTDIR/pullimap.conf" >>"$HOME_local/.config/pullimap/config"
+ fi
cat >>"$HOME_local/.config/interimap/config$n" <<-EOF
@@ -172,7 +176,6 @@ prepare() {
cat <"$TESTDIR/interimap$n.local" >>"$HOME_local/.config/interimap/config$n"
fi
- printf "\\n[remote]\\n" >>"$HOME_local/.config/interimap/config$n"
if [ -s "$home/.dovecot/users" ]; then
cat <<-EOF
username = $u
@@ -184,21 +187,26 @@ prepare() {
command = exec ${home@Q}/.local/bin/doveadm exec imap
null-stderr = NO
EOF
- fi >>"$HOME_local/.config/interimap/config$n"
+ fi >"$HOME_local/.$u.conf"
if [ -f "$TESTDIR/interimap$n.remote" ] || [ -L "$TESTDIR/interimap$n.remote" ]; then
- cat <"$TESTDIR/interimap$n.remote" >>"$HOME_local/.config/interimap/config$n"
+ cat <"$TESTDIR/interimap$n.remote" >>"$HOME_local/.$u.conf"
fi
+
+ { printf "\\n[remote]\\n"; cat <"$HOME_local/.$u.conf"; } >>"$HOME_local/.config/interimap/config$n"
+ { printf "\\n[%s]\\n" "$u"; cat <"$HOME_local/.$u.conf"; } >>"$HOME_local/.config/pullimap/config"
done
}
prepare
# Wrappers for interimap(1) and doveadm(1)
-interimap() {
+interimap() { _interimap_cmd "interimap" "$@"; }
+pullimap() { _interimap_cmd "pullimap" "$@"; }
+_interimap_cmd() {
declare -a ENVIRON=() r=0
+ local script="$1"
+ shift
environ_set "local"
- env -i "${ENVIRON[@]}" perl -I./lib -T ./interimap "$@" 2>"$STDERR" || r=$?
- cat "$STDERR" >&2
- return $r
+ env -i "${ENVIRON[@]}" perl -I./lib -T "./$script" "$@" 2> >(tee "$STDERR" >&2)
}
interimap_init() {
local u="${1-remote}"
@@ -227,8 +235,10 @@ sqlite3() {
# Sample (random) message
sample_message() {
local date="$(date +"%s.%N")"
+ # also try non-conventional addresses for pullimap
+ local sender="$(shuf -n1 -e "sender" "first.last" "foo-bar" \"\" "\"x\\\" #&\\\\y\"" )"
cat <<-EOF
- From: <sender@example.net>
+ From: <$sender@example.net>
To: <recipient@example.net>
Date: $(date -R -d@"$date")
Message-ID: <$date@example.net>
@@ -240,7 +250,7 @@ sample_message() {
# Wrapper for dovecot-lda(1)
deliver() {
- local -a argv
+ declare -a argv
while [ $# -gt 0 ] && [ "$1" != "--" ]; do
argv+=( "$1" )
shift
@@ -433,8 +443,8 @@ passed() {
declare -a ENVIRON=()
environ_set "local"
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 environ_set doveadm interimap interimap_init pullimap _interimap_cmd
+export -f sqlite3 sample_message deliver 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 xcgrep error
[ "$TESTNAME" = "..." ] || printf "%s%s..." "${INDENT-}" "$TESTNAME"
diff --git a/tests/snippets/dovecot/lmtpd.conf b/tests/snippets/dovecot/lmtpd.conf
new file mode 100644
index 0000000..6aa8365
--- /dev/null
+++ b/tests/snippets/dovecot/lmtpd.conf
@@ -0,0 +1,7 @@
+protocols = $protocols lmtp
+
+service lmtp {
+ inet_listener lmtp {
+ port = 10024
+ }
+}