add autotest for message trashing
This commit is contained in:
parent
4b0c5a0cd5
commit
8363dbf2d1
159
src/run-tests.pl
159
src/run-tests.pl
|
@ -128,6 +128,8 @@ sub parse_msg($$$$$)
|
||||||
my $bs = $$cs{$t};
|
my $bs = $$cs{$t};
|
||||||
my ($msr, $n2ur) = ($$bs{messages}, $$bs{num2uid});
|
my ($msr, $n2ur) = ($$bs{messages}, $$bs{num2uid});
|
||||||
|
|
||||||
|
$$cs{"${t}_trash"}{$num} = 1
|
||||||
|
if ($sts =~ s,^#,,);
|
||||||
my $ouid;
|
my $ouid;
|
||||||
my $uids = \@{$$n2ur{$num}};
|
my $uids = \@{$$n2ur{$num}};
|
||||||
if ($sts =~ s,^&$,,) {
|
if ($sts =~ s,^&$,,) {
|
||||||
|
@ -212,6 +214,9 @@ sub parse_chan($;$)
|
||||||
# messages: { uid => [ subject, flags ], ... }
|
# messages: { uid => [ subject, flags ], ... }
|
||||||
far => { max_uid => 0, messages => {}, num2uid => {} },
|
far => { max_uid => 0, messages => {}, num2uid => {} },
|
||||||
near => { max_uid => 0, messages => {}, num2uid => {} },
|
near => { max_uid => 0, messages => {}, num2uid => {} },
|
||||||
|
# trashed messages: { subject => is_placeholder, ... }
|
||||||
|
far_trash => { },
|
||||||
|
near_trash => { },
|
||||||
# entries: [ [ far_uid, near_uid, flags ], ... ]
|
# entries: [ [ far_uid, near_uid, flags ], ... ]
|
||||||
state => { entries => [] }
|
state => { entries => [] }
|
||||||
};
|
};
|
||||||
|
@ -352,30 +357,17 @@ sub readfile($;$)
|
||||||
}
|
}
|
||||||
|
|
||||||
# $path
|
# $path
|
||||||
sub readbox($)
|
sub readbox_impl($$)
|
||||||
{
|
{
|
||||||
my $bn = shift;
|
my ($bn, $cb) = @_;
|
||||||
|
|
||||||
(-d $bn) or
|
|
||||||
die "No mailbox '$bn'.\n";
|
|
||||||
(-d $bn."/tmp" and -d $bn."/new" and -d $bn."/cur") or
|
(-d $bn."/tmp" and -d $bn."/new" and -d $bn."/cur") or
|
||||||
die "Invalid mailbox '$bn'.\n";
|
die "Invalid mailbox '$bn'.\n";
|
||||||
my $uidval = readfile($bn."/.uidvalidity", CHOMP);
|
|
||||||
die "Cannot read UID validity of mailbox '$bn': $!\n" if (!$uidval);
|
|
||||||
my $mu = $$uidval[1];
|
|
||||||
my %ms = ();
|
|
||||||
for my $d ("cur", "new") {
|
for my $d ("cur", "new") {
|
||||||
opendir(DIR, $bn."/".$d) or next;
|
opendir(DIR, $bn."/".$d) or next;
|
||||||
for my $f (grep(!/^\.\.?$/, readdir(DIR))) {
|
for my $f (grep(!/^\.\.?$/, readdir(DIR))) {
|
||||||
my ($uid, $flg, $ph, $num);
|
|
||||||
if ($f =~ /^\d+\.\d+_\d+\.[-[:alnum:]]+,U=(\d+):2,(.*)$/) {
|
|
||||||
($uid, $flg) = (int($1), $2);
|
|
||||||
} else {
|
|
||||||
print STDERR "unrecognided file name '$f' in '$bn'.\n";
|
|
||||||
exit 1;
|
|
||||||
}
|
|
||||||
open(FILE, "<", $bn."/".$d."/".$f) or die "Cannot read message '$f' in '$bn'.\n";
|
open(FILE, "<", $bn."/".$d."/".$f) or die "Cannot read message '$f' in '$bn'.\n";
|
||||||
my $sz = 0;
|
my ($sz, $num, $ph) = (0);
|
||||||
while (<FILE>) {
|
while (<FILE>) {
|
||||||
/^Subject: (\[placeholder\] )?(\d+)$/ && ($ph = defined($1), $num = int($2));
|
/^Subject: (\[placeholder\] )?(\d+)$/ && ($ph = defined($1), $num = int($2));
|
||||||
$sz += length($_);
|
$sz += length($_);
|
||||||
|
@ -385,12 +377,49 @@ sub readbox($)
|
||||||
print STDERR "message '$f' in '$bn' has no identifier.\n";
|
print STDERR "message '$f' in '$bn' has no identifier.\n";
|
||||||
exit 1;
|
exit 1;
|
||||||
}
|
}
|
||||||
@{ $ms{$uid} } = ($num, $flg.($sz>1000?"*":"").($ph?"?":""));
|
$cb->($num, $ph, $sz, $f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# $path
|
||||||
|
sub readbox($)
|
||||||
|
{
|
||||||
|
my $bn = shift;
|
||||||
|
|
||||||
|
(-d $bn) or
|
||||||
|
die "No mailbox '$bn'.\n";
|
||||||
|
my %ms;
|
||||||
|
readbox_impl($bn, sub {
|
||||||
|
my ($num, $ph, $sz, $f) = @_;
|
||||||
|
if ($f !~ /^\d+\.\d+_\d+\.[-[:alnum:]]+,U=(\d+):2,(.*)$/) {
|
||||||
|
print STDERR "unrecognided file name '$f' in '$bn'.\n";
|
||||||
|
exit 1;
|
||||||
|
}
|
||||||
|
my ($uid, $flg) = (int($1), $2);
|
||||||
|
@{$ms{$uid}} = ($num, $flg.($sz > 1000 ? "*" : "").($ph ? "?" : ""));
|
||||||
|
});
|
||||||
|
my $uidval = readfile($bn."/.uidvalidity", CHOMP);
|
||||||
|
die "Cannot read UID validity of mailbox '$bn': $!\n" if (!$uidval);
|
||||||
|
my $mu = $$uidval[1];
|
||||||
return { max_uid => $mu, messages => \%ms };
|
return { max_uid => $mu, messages => \%ms };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# $path
|
||||||
|
sub readtrash($)
|
||||||
|
{
|
||||||
|
my $bn = shift;
|
||||||
|
|
||||||
|
(-d $bn) or
|
||||||
|
return {};
|
||||||
|
my %ms;
|
||||||
|
readbox_impl($bn, sub {
|
||||||
|
my ($num, $ph, undef, undef) = @_;
|
||||||
|
$ms{$num} = $ph;
|
||||||
|
});
|
||||||
|
return \%ms;
|
||||||
|
}
|
||||||
|
|
||||||
# \%fallback_sync_state
|
# \%fallback_sync_state
|
||||||
sub readstate(;$)
|
sub readstate(;$)
|
||||||
{
|
{
|
||||||
|
@ -467,6 +496,8 @@ sub readchan(;$)
|
||||||
return {
|
return {
|
||||||
far => readbox("far"),
|
far => readbox("far"),
|
||||||
near => readbox("near"),
|
near => readbox("near"),
|
||||||
|
far_trash => readtrash("far_trash"),
|
||||||
|
near_trash => readtrash("near_trash"),
|
||||||
state => readstate($fbss)
|
state => readstate($fbss)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -517,6 +548,8 @@ sub mkchan($)
|
||||||
|
|
||||||
mkbox("far", $$cs{far});
|
mkbox("far", $$cs{far});
|
||||||
mkbox("near", $$cs{near});
|
mkbox("near", $$cs{near});
|
||||||
|
rmtree("far_trash");
|
||||||
|
rmtree("near_trash");
|
||||||
mkstate($$cs{state});
|
mkstate($$cs{state});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -560,6 +593,28 @@ sub cmpbox($$$)
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# $box_name, \%actual_box_state, \%reference_box_state
|
||||||
|
sub cmptrash($$$)
|
||||||
|
{
|
||||||
|
my ($bn, $ms, $ref_ms) = @_;
|
||||||
|
|
||||||
|
my $ret = 0;
|
||||||
|
for my $num (sort { $a <=> $b } keys %$ref_ms) {
|
||||||
|
my $ph = $$ms{$num};
|
||||||
|
if (!defined($ph)) {
|
||||||
|
print STDERR "Missing message $bn:".mn($num)."\n";
|
||||||
|
$ret = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for my $num (sort { $a <=> $b } keys %$ms) {
|
||||||
|
if (!defined($$ref_ms{$num})) {
|
||||||
|
print STDERR "Excess message $bn:".mn($num)."\n";
|
||||||
|
$ret = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
sub mapmsg($$)
|
sub mapmsg($$)
|
||||||
{
|
{
|
||||||
my ($uid, $bs) = @_;
|
my ($uid, $bs) = @_;
|
||||||
|
@ -640,6 +695,8 @@ sub cmpchan($$)
|
||||||
my $rslt = 0;
|
my $rslt = 0;
|
||||||
$rslt |= cmpbox("far", $$cs{far}, $$ref_cs{far});
|
$rslt |= cmpbox("far", $$cs{far}, $$ref_cs{far});
|
||||||
$rslt |= cmpbox("near", $$cs{near}, $$ref_cs{near});
|
$rslt |= cmpbox("near", $$cs{near}, $$ref_cs{near});
|
||||||
|
$rslt |= cmptrash("far_trash", $$cs{far_trash}, $$ref_cs{far_trash});
|
||||||
|
$rslt |= cmptrash("near_trash", $$cs{near_trash}, $$ref_cs{near_trash});
|
||||||
$rslt |= cmpstate($cs, $ref_cs);
|
$rslt |= cmpstate($cs, $ref_cs);
|
||||||
return $rslt;
|
return $rslt;
|
||||||
}
|
}
|
||||||
|
@ -763,6 +820,8 @@ sub test_impl($$$$)
|
||||||
|
|
||||||
rmtree "near";
|
rmtree "near";
|
||||||
rmtree "far";
|
rmtree "far";
|
||||||
|
rmtree "near_trash";
|
||||||
|
rmtree "far_trash";
|
||||||
|
|
||||||
for (my $l = 1; $l <= $njl; $l++) {
|
for (my $l = 1; $l <= $njl; $l++) {
|
||||||
mkchan($sx);
|
mkchan($sx);
|
||||||
|
@ -800,6 +859,8 @@ sub test_impl($$$$)
|
||||||
|
|
||||||
rmtree "near";
|
rmtree "near";
|
||||||
rmtree "far";
|
rmtree "far";
|
||||||
|
rmtree "near_trash";
|
||||||
|
rmtree "far_trash";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -842,6 +903,7 @@ sub test($$$$)
|
||||||
# Special commands:
|
# Special commands:
|
||||||
# _ => create phantom message (reserve UID for expunged message)
|
# _ => create phantom message (reserve UID for expunged message)
|
||||||
# ^f => create with flags, duplicating the subject
|
# ^f => create with flags, duplicating the subject
|
||||||
|
# # => create in trash; deletion may follow
|
||||||
# | => use zero UID for state modification, even if msg exists; cmd may follow
|
# | => use zero UID for state modification, even if msg exists; cmd may follow
|
||||||
# & => use zero UID for state identification, even if message exists
|
# & => use zero UID for state identification, even if message exists
|
||||||
# &n => use UID of n'th occurence of subject for state id; command may follow
|
# &n => use UID of n'th occurence of subject for state id; command may follow
|
||||||
|
@ -1080,4 +1142,67 @@ my @X38 = (
|
||||||
);
|
);
|
||||||
test("max messages + expunge", \@x38, \@X38, \@O38);
|
test("max messages + expunge", \@x38, \@X38, \@O38);
|
||||||
|
|
||||||
|
# Trashing
|
||||||
|
|
||||||
|
my @x10 = (
|
||||||
|
E, A, E,
|
||||||
|
A, "*", "*~", "*T",
|
||||||
|
B, "*T", "*^", "",
|
||||||
|
C, "*T", "*", "*T",
|
||||||
|
D, "_", "*", "*",
|
||||||
|
E, "*", "*", "_",
|
||||||
|
L, "*T", "", "",
|
||||||
|
M, "", "", "*T",
|
||||||
|
R, "", "", "*", # Force maxuid in the interrupt-resume test.
|
||||||
|
S, "*", "", "",
|
||||||
|
);
|
||||||
|
|
||||||
|
my @O11 = ("Trash far_trash\n", "Trash near_trash\n",
|
||||||
|
"MaxMessages 20\nExpireUnread yes\nMaxSize 1k\nExpunge Both\n");
|
||||||
|
my @X11 = (
|
||||||
|
R, A, S,
|
||||||
|
A, "", "/", "/",
|
||||||
|
B, "#/", "/", "",
|
||||||
|
C, "#/", "/", "#/",
|
||||||
|
D, "", "/", "#/",
|
||||||
|
E, "#/", "/", "",
|
||||||
|
L, "#/", "", "",
|
||||||
|
M, "", "", "#/",
|
||||||
|
R, "*", "*", "",
|
||||||
|
S, "", "*", "*",
|
||||||
|
);
|
||||||
|
test("trash", \@x10, \@X11, \@O11);
|
||||||
|
|
||||||
|
my @O12 = ("Trash far_trash\n", "Trash near_trash\nTrashNewOnly true\n",
|
||||||
|
"MaxMessages 20\nExpireUnread yes\nMaxSize 1k\nExpunge Both\n");
|
||||||
|
my @X12 = (
|
||||||
|
R, A, S,
|
||||||
|
A, "", "/", "/",
|
||||||
|
B, "#/", "/", "",
|
||||||
|
C, "#/", "/", "/",
|
||||||
|
D, "", "/", "/",
|
||||||
|
E, "#/", "/", "",
|
||||||
|
L, "#/", "", "",
|
||||||
|
M, "", "", "#/",
|
||||||
|
R, "*", "*", "",
|
||||||
|
S, "", "*", "*",
|
||||||
|
);
|
||||||
|
test("trash only new", \@x10, \@X12, \@O12);
|
||||||
|
|
||||||
|
my @O13 = ("Trash far_trash\nTrashRemoteNew true\n", "",
|
||||||
|
"MaxMessages 20\nExpireUnread yes\nMaxSize 1k\nExpunge Both\n");
|
||||||
|
my @X13 = (
|
||||||
|
R, A, S,
|
||||||
|
A, "", "/", "/",
|
||||||
|
B, "#/", "/", "",
|
||||||
|
C, "#/", "/", "/",
|
||||||
|
D, "", "/", "/",
|
||||||
|
E, "#/", "/", "",
|
||||||
|
L, "#/", "", "",
|
||||||
|
M, "#", "", "/",
|
||||||
|
R, "*", "*", "",
|
||||||
|
S, "", "*", "*",
|
||||||
|
);
|
||||||
|
test("trash new remotely", \@x10, \@X13, \@O13);
|
||||||
|
|
||||||
print "OK.\n";
|
print "OK.\n";
|
||||||
|
|
Loading…
Reference in New Issue
Block a user