App-karr

 view release on metacpan or  search on metacpan

t/165-max-runtime-zero-drain.t  view on Meta::CPAN

}
PERL
  return qq{$^X -I"$lib" "$script"};
}

# ---------------------------------------------------------------------------
# Ticket #165
#
# `max_runtime: 0` is documented to disable the per-run timeout entirely, but
# the same knob was also the drain's wall-clock budget. The drain check
# `( time - $loop_start ) >= $max_runtime` is `>= 0` then — always true — so
# the drain ends after a single agent invocation even when `drain: true`
# (default) and the board still has actionable work to do.
# ---------------------------------------------------------------------------

subtest 'max_runtime: 0 does not bound the drain' => sub {
  my $repo  = make_git_repo();
  seed_board( $repo,
    { status => 'todo' }, { status => 'todo' }, { status => 'todo' } );
  my $agent = write_fake_agent( $repo );

  my $f = App::karr::Foundation->new;
  local $ENV{KARR_FAKE_MODE} = 'progress';

  # Same shape as the bug hunt's reproduction: drain: true (default),
  # max_iterations: 3, agent that moves the board on every call. With the bug
  # only one task advances; with the fix all three do.
  my $res = $f->_drain_repo( $repo,
    { command => $agent, max_runtime => 0, max_iterations => 3 } );

  is $res->{outcome}, 'progress', 'outcome progress';
  ok ! $f->_has_actionable_tasks( $repo ),
    'board fully drained (all three tasks advanced) under max_runtime: 0';

  my $done = 0;
  $done++ for grep { task_by_id( $repo, $_ )->status eq 'done' } ( 1, 2, 3 );
  is $done, 3, 'three agent invocations this drain (not one)';
};

subtest 'max_runtime: 60 still bounds the drain (regression guard)' => sub {
  # The fix must not break the documented wall-clock budget. A 60s budget
  # against a no-progress agent (so the drain does not end on
  # !@actionable) and max_iterations: 50 — the wall clock must end the drain
  # well before the iteration cap. We use a sleep whose wall time is well
  # above max_runtime, expect the run to time out (143) and the drain to
  # stop without burning all 50 iterations.
  my $repo  = make_git_repo();
  seed_board( $repo, { status => 'todo' } );
  my $agent = write_fake_agent( $repo );

  my $f = App::karr::Foundation->new;
  local $ENV{KARR_FAKE_MODE} = 'progress';

  # Override the agent with a sleep so each iteration takes longer than the
  # budget and the wall-clock cap is what stops the drain — not the
  # iteration cap, not the actionable check.
  my $start = time;
  $f->_drain_repo( $repo,
    { command => 'sleep 30', max_runtime => 1, max_iterations => 50 } );
  ok time - $start < 25,
    'wall-clock budget ends the drain promptly (not 50 * sleep)';
};

done_testing;



( run in 0.454 second using v1.01-cache-2.11-cpan-aadc1410aed )