autotest: pass containers by reference

this makes function prototypes a lot more useful for parameter checking.
This commit is contained in:
Oswald Buddenhagen 2020-12-18 14:31:16 +01:00
parent 4423a932f3
commit 9fbf5c2f6c

View File

@ -33,7 +33,7 @@ if (!-d "tmp") {
chdir "tmp" or die "Cannot enter temp direcory.\n"; chdir "tmp" or die "Cannot enter temp direcory.\n";
sub show($$$); sub show($$$);
sub test($$$@); sub test($$$$);
################################################################################ ################################################################################
@ -64,7 +64,7 @@ my @X01 = (
[ 10, 0, 10, [ 10, 0, 10,
1, 1, "F", 2, 2, "F", 3, 3, "FS", 4, 4, "", 5, 5, "T", 6, 0, "", 7, 7, "FT", 0, 8, "", 10, 9, "", 9, 10, "" ], 1, 1, "F", 2, 2, "F", 3, 3, "FS", 4, 4, "", 5, 5, "T", 6, 0, "", 7, 7, "FT", 0, 8, "", 10, 9, "", 9, 10, "" ],
); );
test("full", \@x01, \@X01, @O01); test("full", \@x01, \@X01, \@O01);
my @O02 = ("", "", "Expunge Both\n"); my @O02 = ("", "", "Expunge Both\n");
#show("01", "02", "02"); #show("01", "02", "02");
@ -76,7 +76,7 @@ my @X02 = (
[ 10, 0, 10, [ 10, 0, 10,
1, 1, "F", 2, 2, "F", 3, 3, "FS", 4, 4, "", 10, 9, "", 9, 10, "" ], 1, 1, "F", 2, 2, "F", 3, 3, "FS", 4, 4, "", 10, 9, "", 9, 10, "" ],
); );
test("full + expunge both", \@x01, \@X02, @O02); test("full + expunge both", \@x01, \@X02, \@O02);
my @O03 = ("", "", "Expunge Near\n"); my @O03 = ("", "", "Expunge Near\n");
#show("01", "03", "03"); #show("01", "03", "03");
@ -88,7 +88,7 @@ my @X03 = (
[ 10, 0, 10, [ 10, 0, 10,
1, 1, "F", 2, 2, "F", 3, 3, "FS", 4, 4, "", 5, 0, "T", 6, 0, "", 7, 0, "T", 10, 9, "", 9, 10, "" ], 1, 1, "F", 2, 2, "F", 3, 3, "FS", 4, 4, "", 5, 0, "T", 6, 0, "", 7, 0, "T", 10, 9, "", 9, 10, "" ],
); );
test("full + expunge near side", \@x01, \@X03, @O03); test("full + expunge near side", \@x01, \@X03, \@O03);
my @O04 = ("", "", "Sync Pull\n"); my @O04 = ("", "", "Sync Pull\n");
#show("01", "04", "04"); #show("01", "04", "04");
@ -100,7 +100,7 @@ my @X04 = (
[ 9, 0, 0, [ 9, 0, 0,
1, 1, "F", 2, 2, "", 3, 3, "FS", 4, 4, "", 5, 5, "T", 6, 6, "", 7, 7, "FT", 0, 8, "", 9, 10, "" ], 1, 1, "F", 2, 2, "", 3, 3, "FS", 4, 4, "", 5, 5, "T", 6, 6, "", 7, 7, "FT", 0, 8, "", 9, 10, "" ],
); );
test("pull", \@x01, \@X04, @O04); test("pull", \@x01, \@X04, \@O04);
my @O05 = ("", "", "Sync Flags\n"); my @O05 = ("", "", "Sync Flags\n");
#show("01", "05", "05"); #show("01", "05", "05");
@ -112,7 +112,7 @@ my @X05 = (
[ 8, 0, 0, [ 8, 0, 0,
1, 1, "F", 2, 2, "F", 3, 3, "FS", 4, 4, "", 5, 5, "T", 6, 6, "", 7, 7, "FT", 8, 8, "" ], 1, 1, "F", 2, 2, "F", 3, 3, "FS", 4, 4, "", 5, 5, "T", 6, 6, "", 7, 7, "FT", 8, 8, "" ],
); );
test("flags", \@x01, \@X05, @O05); test("flags", \@x01, \@X05, \@O05);
my @O06 = ("", "", "Sync Delete\n"); my @O06 = ("", "", "Sync Delete\n");
#show("01", "06", "06"); #show("01", "06", "06");
@ -124,7 +124,7 @@ my @X06 = (
[ 8, 0, 0, [ 8, 0, 0,
1, 1, "", 2, 2, "", 3, 3, "", 4, 4, "", 5, 5, "", 6, 0, "", 7, 7, "", 0, 8, "" ], 1, 1, "", 2, 2, "", 3, 3, "", 4, 4, "", 5, 5, "", 6, 0, "", 7, 7, "", 0, 8, "" ],
); );
test("deletions", \@x01, \@X06, @O06); test("deletions", \@x01, \@X06, \@O06);
my @O07 = ("", "", "Sync New\n"); my @O07 = ("", "", "Sync New\n");
#show("01", "07", "07"); #show("01", "07", "07");
@ -136,7 +136,7 @@ my @X07 = (
[ 10, 0, 10, [ 10, 0, 10,
1, 1, "", 2, 2, "", 3, 3, "", 4, 4, "", 5, 5, "", 6, 6, "", 7, 7, "", 8, 8, "", 10, 9, "", 9, 10, "" ], 1, 1, "", 2, 2, "", 3, 3, "", 4, 4, "", 5, 5, "", 6, 6, "", 7, 7, "", 8, 8, "", 10, 9, "", 9, 10, "" ],
); );
test("new", \@x01, \@X07, @O07); test("new", \@x01, \@X07, \@O07);
my @O08 = ("", "", "Sync PushFlags PullDelete\n"); my @O08 = ("", "", "Sync PushFlags PullDelete\n");
#show("01", "08", "08"); #show("01", "08", "08");
@ -148,7 +148,7 @@ my @X08 = (
[ 8, 0, 0, [ 8, 0, 0,
1, 1, "", 2, 2, "F", 3, 3, "F", 4, 4, "", 5, 5, "", 6, 6, "", 7, 7, "", 0, 8, "" ], 1, 1, "", 2, 2, "F", 3, 3, "F", 4, 4, "", 5, 5, "", 6, 6, "", 7, 7, "", 0, 8, "" ],
); );
test("push flags + pull deletions", \@x01, \@X08, @O08); test("push flags + pull deletions", \@x01, \@X08, \@O08);
# size restriction tests # size restriction tests
@ -171,7 +171,7 @@ my @X11 = (
[ 3, 0, 3, [ 3, 0, 3,
3, 1, "<", 1, 2, "", 2, 3, ">" ], 3, 1, "<", 1, 2, "", 2, 3, ">" ],
); );
test("max size", \@x10, \@X11, @O11); test("max size", \@x10, \@X11, \@O11);
my @x22 = ( my @x22 = (
[ 3, [ 3,
@ -191,7 +191,7 @@ my @X22 = (
[ 4, 0, 4, [ 4, 0, 4,
4, 1, "F", 3, 0, "T", 1, 2, "", 2, 4, "" ], 4, 1, "F", 3, 0, "T", 1, 2, "", 2, 4, "" ],
); );
test("max size + flagging", \@x22, \@X22, @O11); test("max size + flagging", \@x22, \@X22, \@O11);
my @x23 = ( my @x23 = (
[ 2, [ 2,
@ -210,7 +210,7 @@ my @X23 = (
[ 3, 0, 3, [ 3, 0, 3,
3, 1, "F", 1, 2, "", 2, 3, "F" ] 3, 1, "F", 1, 2, "", 2, 3, "F" ]
); );
test("max size + initial flagging", \@x23, \@X23, @O11); test("max size + initial flagging", \@x23, \@X23, \@O11);
my @x24 = ( my @x24 = (
[ 3, [ 3,
@ -229,7 +229,7 @@ my @X24 = (
[ 3, 0, 3, [ 3, 0, 3,
1, 1, "", 2, 2, ">", 3, 3, "F" ], 1, 1, "", 2, 2, ">", 3, 3, "F" ],
); );
test("max size (pre-1.4 legacy)", \@x24, \@X24, @O11); test("max size (pre-1.4 legacy)", \@x24, \@X24, \@O11);
# expiration tests # expiration tests
@ -252,7 +252,7 @@ my @X31 = (
[ 6, 3, 5, [ 6, 3, 5,
1, 1, "F", 2, 2, "", 4, 3, "", 5, 4, "S", 6, 5, "" ], 1, 1, "F", 2, 2, "", 4, 3, "", 5, 4, "S", 6, 5, "" ],
); );
test("max messages", \@x30, \@X31, @O31); test("max messages", \@x30, \@X31, \@O31);
my @O32 = ("", "", "MaxMessages 3\nExpireUnread yes\n"); my @O32 = ("", "", "MaxMessages 3\nExpireUnread yes\n");
#show("30", "32", "32"); #show("30", "32", "32");
@ -264,7 +264,7 @@ my @X32 = (
[ 6, 3, 4, [ 6, 3, 4,
1, 1, "F", 4, 2, "", 5, 3, "S", 6, 4, "" ], 1, 1, "F", 4, 2, "", 5, 3, "S", 6, 4, "" ],
); );
test("max messages vs. unread", \@x30, \@X32, @O32); test("max messages vs. unread", \@x30, \@X32, \@O32);
my @x50 = ( my @x50 = (
[ 6, [ 6,
@ -285,7 +285,7 @@ my @X51 = (
[ 6, 3, 6, [ 6, 3, 6,
2, 2, "FS", 4, 4, "", 5, 5, "", 6, 6, "" ], 2, 2, "FS", 4, 4, "", 5, 5, "", 6, 6, "" ],
); );
test("max messages + expunge", \@x50, \@X51, @O51); test("max messages + expunge", \@x50, \@X51, \@O51);
################################################################################ ################################################################################
@ -304,9 +304,11 @@ sub qm($)
return $_; return $_;
} }
# $far, $near, $channel # [ $far, $near, $channel ]
sub writecfg($$$) sub writecfg($)
{ {
my ($sfx) = @_;
open(FILE, ">", ".mbsyncrc") or open(FILE, ">", ".mbsyncrc") or
die "Cannot open .mbsyncrc.\n"; die "Cannot open .mbsyncrc.\n";
print FILE print FILE
@ -315,16 +317,16 @@ sub writecfg($$$)
MaildirStore far MaildirStore far
Path ./ Path ./
Inbox ./far Inbox ./far
".shift()." ".$$sfx[0]."
MaildirStore near MaildirStore near
Path ./ Path ./
Inbox ./near Inbox ./near
".shift()." ".$$sfx[1]."
Channel test Channel test
Far :far: Far :far:
Near :near: Near :near:
SyncState * SyncState *
".shift(); ".$$sfx[2];
close FILE; close FILE;
} }
@ -335,6 +337,7 @@ sub killcfg()
} }
# $run_async, $mbsync_options, $log_file # $run_async, $mbsync_options, $log_file
# Return: $exit_code, \@mbsync_output
sub runsync($$$) sub runsync($$$)
{ {
my ($async, $flags, $file) = @_; my ($async, $flags, $file) = @_;
@ -355,11 +358,12 @@ sub runsync($$$)
print FILE @out; print FILE @out;
close FILE; close FILE;
} }
return $?, @out; return $?, \@out;
} }
# $path # $path
# Return: $max_uid, { uid => [ seq, flags ] }
sub readbox($) sub readbox($)
{ {
my $bn = shift; my $bn = shift;
@ -397,7 +401,7 @@ sub readbox($)
@{ $ms{$uid} } = ($num, $flg.($sz>1000?"*":"").($ph?"?":"")); @{ $ms{$uid} } = ($num, $flg.($sz>1000?"*":"").($ph?"?":""));
} }
} }
return ($mu, %ms); return $mu, \%ms;
} }
# $boxname # $boxname
@ -408,12 +412,12 @@ sub showbox($)
{ {
my ($bn) = @_; my ($bn) = @_;
my ($mu, %ms) = readbox($bn); my ($mu, $ms) = readbox($bn);
my @MS = ($mu); my @bc = ($mu);
for my $uid (sort { $a <=> $b } keys %ms) { for my $uid (sort { $a <=> $b } keys %$ms) {
push @MS, $ms{$uid}[0], $uid, $ms{$uid}[1]; push @bc, $$ms{$uid}[0], $uid, $$ms{$uid}[1];
} }
printbox($bn, @MS); printbox($bn, \@bc);
} }
# $filename # $filename
@ -453,7 +457,7 @@ sub showstate($)
/^(\d+) (\d+) (.*)$/; /^(\d+) (\d+) (.*)$/;
push @T, $1, $2, $3; push @T, $1, $2, $3;
} }
printstate(@T); printstate(\@T);
} }
# $filename # $filename
@ -470,37 +474,37 @@ sub showchan($)
sub show($$$) sub show($$$)
{ {
my ($sx, $tx, $sfxn) = @_; my ($sx, $tx, $sfxn) = @_;
my (@sp, @sfx); my ($sp, $sfx);
eval "\@sp = \@x$sx"; eval "\$sp = \\\@x$sx";
eval "\@sfx = \@O$sfxn"; eval "\$sfx = \\\@O$sfxn";
mkchan($sp[0], $sp[1], @{ $sp[2] }); mkchan($$sp[0], $$sp[1], $$sp[2]);
print "my \@x$sx = (\n"; print "my \@x$sx = (\n";
showchan("near/.mbsyncstate"); showchan("near/.mbsyncstate");
print ");\n"; print ");\n";
&writecfg(@sfx); writecfg($sfx);
runsync(0, "", ""); runsync(0, "", "");
killcfg(); killcfg();
print "my \@X$tx = (\n"; print "my \@X$tx = (\n";
showchan("near/.mbsyncstate"); showchan("near/.mbsyncstate");
print ");\n"; print ");\n";
print "test(\"\", \\\@x$sx, \\\@X$tx, \@O$sfxn);\n\n"; print "test(\"\", \\\@x$sx, \\\@X$tx, \\\@O$sfxn);\n\n";
rmtree "near"; rmtree "near";
rmtree "far"; rmtree "far";
} }
# $boxname, $maxuid, @msgs # $box_name, \@box_state
sub mkbox($$@) sub mkbox($$)
{ {
my ($bn, $mu, @ms) = @_; my ($bn, $bs) = @_;
rmtree($bn); rmtree($bn);
(mkdir($bn) and mkdir($bn."/tmp") and mkdir($bn."/new") and mkdir($bn."/cur")) or (mkdir($bn) and mkdir($bn."/tmp") and mkdir($bn."/new") and mkdir($bn."/cur")) or
die "Cannot create mailbox $bn.\n"; die "Cannot create mailbox $bn.\n";
open(FILE, ">", $bn."/.uidvalidity") or die "Cannot create UID validity for mailbox $bn.\n"; open(FILE, ">", $bn."/.uidvalidity") or die "Cannot create UID validity for mailbox $bn.\n";
print FILE "1\n$mu\n"; print FILE "1\n$$bs[0]\n";
close FILE; close FILE;
while (@ms) { for (my $i = 1; $i < @$bs; $i += 3) {
my ($num, $uid, $flg) = (shift @ms, shift @ms, shift @ms); my ($num, $uid, $flg) = ($$bs[$i], $$bs[$i + 1], $$bs[$i + 2]);
my $big = $flg =~ s/\*//; my $big = $flg =~ s/\*//;
my $ph = $flg =~ s/\?//; my $ph = $flg =~ s/\?//;
open(FILE, ">", $bn."/".($flg =~ /S/ ? "cur" : "new")."/0.1_".$num.".local,U=".$uid.":2,".$flg) or open(FILE, ">", $bn."/".($flg =~ /S/ ? "cur" : "new")."/0.1_".$num.".local,U=".$uid.":2,".$flg) or
@ -510,35 +514,35 @@ sub mkbox($$@)
} }
} }
# \@far, \@near, @syncstate # \@far_state, \@near_state, \@sync_state
sub mkchan($$@) sub mkchan($$$)
{ {
my ($m, $s, @t) = @_; my ($f, $n, $t) = @_;
&mkbox("far", @{ $m }); mkbox("far", $f);
&mkbox("near", @{ $s }); mkbox("near", $n);
open(FILE, ">", "near/.mbsyncstate") or open(FILE, ">", "near/.mbsyncstate") or
die "Cannot create sync state.\n"; die "Cannot create sync state.\n";
print FILE "FarUidValidity 1\nMaxPulledUid ".shift(@t)."\n". print FILE "FarUidValidity 1\nMaxPulledUid ".$$t[0]."\n".
"NearUidValidity 1\nMaxExpiredFarUid ".shift(@t)."\nMaxPushedUid ".shift(@t)."\n\n"; "NearUidValidity 1\nMaxExpiredFarUid ".$$t[1]."\nMaxPushedUid ".$$t[2]."\n\n";
while (@t) { for (my $i = 3; $i < @$t; $i += 3) {
print FILE shift(@t)." ".shift(@t)." ".shift(@t)."\n"; print FILE $$t[$i]." ".$$t[$i + 1]." ".$$t[$i + 2]."\n";
} }
close FILE; close FILE;
} }
# $boxname, $maxuid, @msgs # $box_name, \@box_state
sub ckbox($$@) sub ckbox($$)
{ {
my ($bn, $MU, @MS) = @_; my ($bn, $bs) = @_;
my ($mu, %ms) = readbox($bn); my ($mu, $ms) = readbox($bn);
if ($mu != $MU) { if ($mu != $$bs[0]) {
print STDERR "MAXUID mismatch for '$bn' (got $mu, wanted $MU).\n"; print STDERR "MAXUID mismatch for '$bn' (got $mu, wanted $$bs[0]).\n";
return 1; return 1;
} }
while (@MS) { for (my $i = 1; $i < @$bs; $i += 3) {
my ($num, $uid, $flg) = (shift @MS, shift @MS, shift @MS); my ($num, $uid, $flg) = ($$bs[$i], $$bs[$i + 1], $$bs[$i + 2]);
my $m = delete $ms{$uid}; my $m = delete $$ms{$uid};
if (!defined $m) { if (!defined $m) {
print STDERR "No message $bn:$uid.\n"; print STDERR "No message $bn:$uid.\n";
return 1; return 1;
@ -552,23 +556,23 @@ sub ckbox($$@)
return 1; return 1;
} }
} }
if (%ms) { if (%$ms) {
print STDERR "Excess messages in '$bn': ".join(", ", sort({$a <=> $b } keys(%ms))).".\n"; print STDERR "Excess messages in '$bn': ".join(", ", sort({ $a <=> $b } keys(%$ms))).".\n";
return 1; return 1;
} }
return 0; return 0;
} }
# $filename, @syncstate # $state_file, \@sync_state
sub ckstate($@) sub ckstate($$)
{ {
my ($fn, $fmaxuid, $maxxfuid, $nmaxuid, @T) = @_; my ($fn, $t) = @_;
my %hdr; my %hdr;
$hdr{'FarUidValidity'} = "1"; $hdr{'FarUidValidity'} = "1";
$hdr{'NearUidValidity'} = "1"; $hdr{'NearUidValidity'} = "1";
$hdr{'MaxPulledUid'} = $fmaxuid; $hdr{'MaxPulledUid'} = $$t[0];
$hdr{'MaxPushedUid'} = $nmaxuid; $hdr{'MaxPushedUid'} = $$t[2];
$hdr{'MaxExpiredFarUid'} = $maxxfuid if ($maxxfuid ne 0); $hdr{'MaxExpiredFarUid'} = $$t[1] if ($$t[1] ne 0);
open(FILE, "<", $fn) or die "Cannot read sync state $fn.\n"; open(FILE, "<", $fn) or die "Cannot read sync state $fn.\n";
chomp(my @ls = <FILE>); chomp(my @ls = <FILE>);
close FILE; close FILE;
@ -598,66 +602,68 @@ sub ckstate($@)
print STDERR "Keys missing from sync state header: @ky\n"; print STDERR "Keys missing from sync state header: @ky\n";
return 1; return 1;
} }
my $i = 3;
for my $l (@ls) { for my $l (@ls) {
if (!@T) { if ($i == @$t) {
print STDERR "Excess sync state entry: '$l'.\n"; print STDERR "Excess sync state entry: '$l'.\n";
return 1; return 1;
} }
my $xl = shift(@T)." ".shift(@T)." ".shift(@T); my $xl = $$t[$i]." ".$$t[$i + 1]." ".$$t[$i + 2];
if ($l ne $xl) { if ($l ne $xl) {
print STDERR "Sync state entry mismatch: '$l' instead of '$xl'.\n"; print STDERR "Sync state entry mismatch: '$l' instead of '$xl'.\n";
return 1; return 1;
} }
$i += 3;
} }
if (@T) { if ($i < @$t) {
print STDERR "Missing sync state entry: '".shift(@T)." ".shift(@T)." ".shift(@T)."'.\n"; print STDERR "Missing sync state entry: '".$$t[$i]." ".$$t[$i + 1]." ".$$t[$i + 2]."'.\n";
return 1; return 1;
} }
return 0; return 0;
} }
# $statefile, \@chan_state # $state_file, \@chan_state
sub ckchan($$) sub ckchan($$)
{ {
my ($F, $cs) = @_; my ($fn, $cs) = @_;
my $rslt = ckstate($F, @{ $$cs[2] }); my $rslt = ckstate($fn, $$cs[2]);
$rslt |= &ckbox("far", @{ $$cs[0] }); $rslt |= ckbox("far", $$cs[0]);
$rslt |= &ckbox("near", @{ $$cs[1] }); $rslt |= ckbox("near", $$cs[1]);
return $rslt; return $rslt;
} }
# $boxname, $maxuid, @msgs # $box_name, \@box_state
sub printbox($$@) sub printbox($$)
{ {
my ($bn, $mu, @ms) = @_; my ($bn, $bs) = @_;
print " [ $mu,\n "; print " [ $$bs[0],\n ";
my $frst = 1; my $frst = 1;
while (@ms) { for (my $i = 1; $i < @$bs; $i += 3) {
if ($frst) { if ($frst) {
$frst = 0; $frst = 0;
} else { } else {
print ", "; print ", ";
} }
print mn(shift(@ms)).", ".shift(@ms).", \"".shift(@ms)."\""; print mn($$bs[$i]).", ".$$bs[$i + 1].", \"".$$bs[$i + 2]."\"";
} }
print " ],\n"; print " ],\n";
} }
# @syncstate # \@sync_state
sub printstate(@) sub printstate($)
{ {
my (@t) = @_; my ($t) = @_;
print " [ ".shift(@t).", ".shift(@t).", ".shift(@t).",\n "; print " [ ".$$t[0].", ".$$t[1].", ".$$t[2].",\n ";
my $frst = 1; my $frst = 1;
while (@t) { for (my $i = 3; $i < @$t; $i += 3) {
if ($frst) { if ($frst) {
$frst = 0; $frst = 0;
} else { } else {
print ", "; print ", ";
} }
print((shift(@t) // "??").", ".(shift(@t) // "??").", \"".(shift(@t) // "??")."\""); print(($$t[$i] // "??").", ".($$t[$i + 1] // "??").", \"".($$t[$i + 2] // "??")."\"");
} }
print " ],\n"; print " ],\n";
} }
@ -667,9 +673,9 @@ sub printchan($)
{ {
my ($cs) = @_; my ($cs) = @_;
&printbox("far", @{ $$cs[0] }); printbox("far", $$cs[0]);
&printbox("near", @{ $$cs[1] }); printbox("near", $$cs[1]);
printstate(@{ $$cs[2] }); printstate($$cs[2]);
} }
sub readfile($) sub readfile($)
@ -679,22 +685,22 @@ sub readfile($)
open(FILE, $file) or return; open(FILE, $file) or return;
my @nj = <FILE>; my @nj = <FILE>;
close FILE; close FILE;
return @nj; return \@nj;
} }
# $run_async, \@source_state, \@target_state, @channel_configs # $run_async, \@source_state, \@target_state, \@channel_configs
sub test_impl($$$@) sub test_impl($$$$)
{ {
my ($async, $sx, $tx, @sfx) = @_; my ($async, $sx, $tx, $sfx) = @_;
mkchan($$sx[0], $$sx[1], @{ $$sx[2] }); mkchan($$sx[0], $$sx[1], $$sx[2]);
my ($xc, @ret) = runsync($async, "-Tj", "1-initial.log"); my ($xc, $ret) = runsync($async, "-Tj", "1-initial.log");
if ($xc || ckchan("near/.mbsyncstate.new", $tx)) { if ($xc || ckchan("near/.mbsyncstate.new", $tx)) {
print "Input:\n"; print "Input:\n";
printchan($sx); printchan($sx);
print "Options:\n"; print "Options:\n";
print " [ ".join(", ", map('"'.qm($_).'"', @sfx))." ]\n"; print " [ ".join(", ", map('"'.qm($_).'"', @$sfx))." ]\n";
if (!$xc) { if (!$xc) {
print "Expected result:\n"; print "Expected result:\n";
printchan($tx); printchan($tx);
@ -702,72 +708,72 @@ sub test_impl($$$@)
showchan("near/.mbsyncstate.new"); showchan("near/.mbsyncstate.new");
} }
print "Debug output:\n"; print "Debug output:\n";
print @ret; print @$ret;
exit 1; exit 1;
} }
my @nj = readfile("near/.mbsyncstate.journal"); my $nj = readfile("near/.mbsyncstate.journal");
my ($jxc, @jret) = runsync($async, "-0 --no-expunge", "2-replay.log"); my ($jxc, $jret) = runsync($async, "-0 --no-expunge", "2-replay.log");
if ($jxc || ckstate("near/.mbsyncstate", @{ $$tx[2] })) { if ($jxc || ckstate("near/.mbsyncstate", $$tx[2])) {
print "Journal replay failed.\n"; print "Journal replay failed.\n";
print "Options:\n"; print "Options:\n";
print " [ ".join(", ", map('"'.qm($_).'"', @sfx))." ], [ \"-0\", \"--no-expunge\" ]\n"; print " [ ".join(", ", map('"'.qm($_).'"', @$sfx))." ], [ \"-0\", \"--no-expunge\" ]\n";
print "Old State:\n"; print "Old State:\n";
printstate(@{ $$sx[2] }); printstate($$sx[2]);
print "Journal:\n".join("", @nj)."\n"; print "Journal:\n".join("", @$nj)."\n";
if (!$jxc) { if (!$jxc) {
print "Expected New State:\n"; print "Expected New State:\n";
printstate(@{ $$tx[2] }); printstate($$tx[2]);
print "New State:\n"; print "New State:\n";
showstate("near/.mbsyncstate"); showstate("near/.mbsyncstate");
} }
print "Debug output:\n"; print "Debug output:\n";
print @jret; print @$jret;
exit 1; exit 1;
} }
my ($ixc, @iret) = runsync($async, "", "3-verify.log"); my ($ixc, $iret) = runsync($async, "", "3-verify.log");
if ($ixc || ckchan("near/.mbsyncstate", $tx)) { if ($ixc || ckchan("near/.mbsyncstate", $tx)) {
print "Idempotence verification run failed.\n"; print "Idempotence verification run failed.\n";
print "Input == Expected result:\n"; print "Input == Expected result:\n";
printchan($tx); printchan($tx);
print "Options:\n"; print "Options:\n";
print " [ ".join(", ", map('"'.qm($_).'"', @sfx))." ]\n"; print " [ ".join(", ", map('"'.qm($_).'"', @$sfx))." ]\n";
if (!$ixc) { if (!$ixc) {
print "Actual result:\n"; print "Actual result:\n";
showchan("near/.mbsyncstate"); showchan("near/.mbsyncstate");
} }
print "Debug output:\n"; print "Debug output:\n";
print @iret; print @$iret;
exit 1; exit 1;
} }
rmtree "near"; rmtree "near";
rmtree "far"; rmtree "far";
my $njl = (@nj - 1) * 2; my $njl = (@$nj - 1) * 2;
for (my $l = 1; $l <= $njl; $l++) { for (my $l = 1; $l <= $njl; $l++) {
mkchan($$sx[0], $$sx[1], @{ $$sx[2] }); mkchan($$sx[0], $$sx[1], $$sx[2]);
my ($nxc, @nret) = runsync($async, "-Tj$l", "4-interrupt.log"); my ($nxc, $nret) = runsync($async, "-Tj$l", "4-interrupt.log");
if ($nxc != (100 + ($l & 1)) << 8) { if ($nxc != (100 + ($l & 1)) << 8) {
print "Interrupting at step $l/$njl failed.\n"; print "Interrupting at step $l/$njl failed.\n";
print "Debug output:\n"; print "Debug output:\n";
print @nret; print @$nret;
exit 1; exit 1;
} }
($nxc, @nret) = runsync($async, "-Tj", "5-resume.log"); ($nxc, $nret) = runsync($async, "-Tj", "5-resume.log");
if ($nxc || ckchan("near/.mbsyncstate.new", $tx)) { if ($nxc || ckchan("near/.mbsyncstate.new", $tx)) {
print "Resuming from step $l/$njl failed.\n"; print "Resuming from step $l/$njl failed.\n";
print "Input:\n"; print "Input:\n";
printchan($sx); printchan($sx);
print "Options:\n"; print "Options:\n";
print " [ ".join(", ", map('"'.qm($_).'"', @sfx))." ]\n"; print " [ ".join(", ", map('"'.qm($_).'"', @$sfx))." ]\n";
my @nnj = readfile("near/.mbsyncstate.journal"); my $nnj = readfile("near/.mbsyncstate.journal");
my $ln = int($l / 2); my $ln = int($l / 2);
print "Journal:\n".join("", @nnj[0..$ln])."-------\n".join("", @nnj[($ln + 1)..$#nnj])."\n"; print "Journal:\n".join("", @$nnj[0..$ln])."-------\n".join("", @$nnj[($ln + 1)..$#$nnj])."\n";
print "Full journal:\n".join("", @nj)."\n"; print "Full journal:\n".join("", @$nj)."\n";
if (!$nxc) { if (!$nxc) {
print "Expected result:\n"; print "Expected result:\n";
printchan($tx); printchan($tx);
@ -775,7 +781,7 @@ sub test_impl($$$@)
showchan("near/.mbsyncstate.new"); showchan("near/.mbsyncstate.new");
} }
print "Debug output:\n"; print "Debug output:\n";
print @nret; print @$nret;
exit 1; exit 1;
} }
@ -784,17 +790,17 @@ sub test_impl($$$@)
} }
} }
# $title, \@source_state, \@target_state, @channel_configs # $title, \@source_state, \@target_state, \@channel_configs
sub test($$$@) sub test($$$$)
{ {
my ($ttl, $sx, $tx, @sfx) = @_; my ($ttl, $sx, $tx, $sfx) = @_;
return 0 if (scalar(@ARGV) && !grep { $_ eq $ttl } @ARGV); return 0 if (scalar(@ARGV) && !grep { $_ eq $ttl } @ARGV);
print "Testing: ".$ttl." ...\n"; print "Testing: ".$ttl." ...\n";
&writecfg(@sfx); writecfg($sfx);
test_impl(0, $sx, $tx, @sfx); test_impl(0, $sx, $tx, $sfx);
test_impl(1, $sx, $tx, @sfx); test_impl(1, $sx, $tx, $sfx);
killcfg(); killcfg();
} }