rework interrupt-resume autotesting

instead of doing two runs for each journal entry, do one run for each
"write" operation, be it a journal entry or a writing driver call. this
saves runs between which no visible change occurred, which yields a 33%
improvement in runtime.

we now also exclude the final entry purge from the test, as it's really
kinda pointless, and we'd have to jump through additional hoops
(simulate an atomic commit of the state) to make it reliable in all
cases.

note that this also adds a few steps, which actually uncovered a bug in
the expunge sequencing.

amends efd72b85.
This commit is contained in:
Oswald Buddenhagen 2022-03-01 15:16:07 +01:00
parent 58a69a5b63
commit d74af51fa1
8 changed files with 54 additions and 15 deletions

View File

@ -124,7 +124,7 @@ BIT_ENUM(
// Global options // Global options
extern int Verbosity; extern int Verbosity;
extern int DFlags; extern int DFlags;
extern int JLimit; extern int JLimit, JCount;
extern int UseFSync; extern int UseFSync;
// Global constants (inited by main()) // Global constants (inited by main())
@ -132,6 +132,7 @@ extern int Pid;
extern char Hostname[256]; extern char Hostname[256];
extern const char *Home; extern const char *Home;
void countStep( void );
void stats( void ); void stats( void );
/* util.c */ /* util.c */

View File

@ -212,6 +212,7 @@ proxy_@name@_cb( @decl_cb_args@void *aux )
@name@_cmd_t *cmd = (@name@_cmd_t *)aux; @name@_cmd_t *cmd = (@name@_cmd_t *)aux;
proxy_store_t *ctx = cmd->ctx; proxy_store_t *ctx = cmd->ctx;
@count_step@
@print_cb_args_tpl@ @print_cb_args_tpl@
cmd->callback( @pass_cb_args@cmd->callback_aux ); cmd->callback( @pass_cb_args@cmd->callback_aux );
debug( "%s[% 2d] Callback leave @name@\n", ctx->label, cmd->tag ); debug( "%s[% 2d] Callback leave @name@\n", ctx->label, cmd->tag );
@ -251,6 +252,10 @@ static @type@proxy_@name@( store_t *gctx@decl_args@, void (*cb)( @decl_cb_args@v
debug( " %s\n", box->string ); debug( " %s\n", box->string );
//# END //# END
//# DEFINE create_box_counted 1
//# DEFINE delete_box_counted 1
//# DEFINE prepare_load_box_print_fmt_args , opts=%s //# DEFINE prepare_load_box_print_fmt_args , opts=%s
//# DEFINE prepare_load_box_print_pass_args , fmt_opts( opts ).str //# DEFINE prepare_load_box_print_pass_args , fmt_opts( opts ).str
//# DEFINE prepare_load_box_print_fmt_ret %s //# DEFINE prepare_load_box_print_fmt_ret %s
@ -313,13 +318,18 @@ static @type@proxy_@name@( store_t *gctx@decl_args@, void (*cb)( @decl_cb_args@v
fflush( stdout ); fflush( stdout );
} }
//# END //# END
//# DEFINE store_msg_counted 1
//# DEFINE set_msg_flags_checked 1 //# DEFINE set_msg_flags_checked 1
//# DEFINE set_msg_flags_print_fmt_args , uid=%u, add=%s, del=%s //# DEFINE set_msg_flags_print_fmt_args , uid=%u, add=%s, del=%s
//# DEFINE set_msg_flags_print_pass_args , cmd->uid, fmt_flags( cmd->add ).str, fmt_flags( cmd->del ).str //# DEFINE set_msg_flags_print_pass_args , cmd->uid, fmt_flags( cmd->add ).str, fmt_flags( cmd->del ).str
//# DEFINE set_msg_flags_counted 1
//# DEFINE trash_msg_print_fmt_args , uid=%u //# DEFINE trash_msg_print_fmt_args , uid=%u
//# DEFINE trash_msg_print_pass_args , cmd->msg->uid //# DEFINE trash_msg_print_pass_args , cmd->msg->uid
//# DEFINE trash_msg_counted 1
//# DEFINE close_box_counted 1
//# DEFINE commit_cmds_print_args //# DEFINE commit_cmds_print_args
proxy_flush_checked_cmds( ctx ); proxy_flush_checked_cmds( ctx );

View File

@ -176,7 +176,13 @@ for (@ptypes) {
$replace{'print_fmt_args'} = make_format($cmd_args); $replace{'print_fmt_args'} = make_format($cmd_args);
} }
for (keys %defines) { for (keys %defines) {
$replace{$1} = delete $defines{$_} if (/^${cmd_name}_(.*)$/); next if (!/^${cmd_name}_(.*)$/);
my ($key, $val) = ($1, delete $defines{$_});
if ($key eq 'counted') {
$replace{count_step} = "countStep();\n";
} else {
$replace{$key} = $val;
}
} }
my %used; my %used;
my $text = $templates{$template}; my $text = $templates{$template};

View File

@ -132,6 +132,13 @@ crashHandler( int n )
} }
#endif #endif
void
countStep( void )
{
if (!--JLimit)
exit( 100 );
}
int int
main( int argc, char **argv ) main( int argc, char **argv )
{ {

View File

@ -783,10 +783,19 @@ sub test_impl($$$$)
exit 1; exit 1;
} }
my ($nj, $njl) = (undef, 0); my ($nj, $njl, $nje) = (undef, 0, 0);
if ($$rtx{state} != $$sx{state}) { if ($$rtx{state} != $$sx{state}) {
$nj = readfile("near/.mbsyncstate.journal"); $nj = readfile("near/.mbsyncstate.journal");
$njl = (@$nj - 1) * 2; STEPS: {
for (reverse @$ret) {
if (/^### (\d+) steps, (\d+) entries ###$/) {
$njl = int($1) - 1;
$nje = int($2);
last STEPS;
}
}
die("Cannot extract step count.\n");
}
my ($jxc, $jret) = runsync($async, "-0 --no-expunge", "2-replay.log"); my ($jxc, $jret) = runsync($async, "-0 --no-expunge", "2-replay.log");
my $jrcs = readstate() if (!$jxc); my $jrcs = readstate() if (!$jxc);
@ -835,13 +844,15 @@ sub test_impl($$$$)
mkchan($sx); mkchan($sx);
my ($nxc, $nret) = runsync($async, "-Ts$l", "4-interrupt.log"); my ($nxc, $nret) = runsync($async, "-Ts$l", "4-interrupt.log");
if ($nxc != (100 + ($l & 1)) << 8) { if ($nxc != 100 << 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;
} }
my $pnnj = readfile("near/.mbsyncstate.journal");
($nxc, $nret) = runsync($async, "-Tj", "5-resume.log"); ($nxc, $nret) = runsync($async, "-Tj", "5-resume.log");
my $nrtx = readchan($$sx{state}) if (!$nxc); my $nrtx = readchan($$sx{state}) if (!$nxc);
if ($nxc || cmpchan($nrtx, $tx)) { if ($nxc || cmpchan($nrtx, $tx)) {
@ -851,9 +862,9 @@ sub test_impl($$$$)
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 = $#$pnnj;
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[0..$nje])."=======\n".join("", @$nj[($nje + 1)..$#$nj])."\n";
if (!$nxc) { if (!$nxc) {
print "Expected result:\n"; print "Expected result:\n";
printchan($tx); printchan($tx);

View File

@ -1719,9 +1719,15 @@ box_closed_p2( sync_vars_t *svars, int t )
if (!(svars->state[t^1] & ST_CLOSED)) if (!(svars->state[t^1] & ST_CLOSED))
return; return;
// All the journalling done in this function is merely for the autotest - // All logging done in this function is merely for the journal replay
// the operations are idempotent, and we're about to commit the new state // autotest - the operations are idempotent, and we're about to commit
// right afterwards anyway. // the new state right afterwards anyway. Therefore, it would also
// make no sense to cover it by the interrupt-resume autotest (which
// would also add unreasonable complexity, as the maxuid bumps and entry
// purge must be consistent).
if (DFlags & KEEPJOURNAL)
printf( "### %d steps, %d entries ###\n", -JLimit, JCount );
for (t = 0; t < 2; t++) { for (t = 0; t < 2; t++) {
// Committing maxuid is delayed until all messages were propagated, to // Committing maxuid is delayed until all messages were propagated, to

View File

@ -439,8 +439,6 @@ jFprintf( sync_vars_t *svars, const char *msg, ... )
{ {
va_list va; va_list va;
if (JLimit && !--JLimit)
exit( 101 );
if (!svars->jfp) { if (!svars->jfp) {
create_state( svars ); create_state( svars );
if (!(svars->jfp = fopen( svars->jname, svars->replayed ? "a" : "w" ))) { if (!(svars->jfp = fopen( svars->jname, svars->replayed ? "a" : "w" ))) {
@ -454,8 +452,8 @@ jFprintf( sync_vars_t *svars, const char *msg, ... )
va_start( va, msg ); va_start( va, msg );
vFprintf( svars->jfp, msg, va ); vFprintf( svars->jfp, msg, va );
va_end( va ); va_end( va );
if (JLimit && !--JLimit) countStep();
exit( 100 ); JCount++;
} }
void void

View File

@ -15,7 +15,7 @@
int Verbosity = TERSE; int Verbosity = TERSE;
int DFlags; int DFlags;
int JLimit; int JLimit, JCount;
int UseFSync = 1; int UseFSync = 1;
int Pid; int Pid;