A TAP Parser In 30 Lines of Code

Ovid on 2008-04-14T20:41:38

I recently posted about a TAP parser in 40 lines of code. Because I just uploaded a new Test::TAP (general cleanup and a pre-5.6 bug), I now have it in 30 lines of code without golfing. I could make it even shorter if I wanted to, but why?

sub _tap_failed {
    my $tap      = shift;
    my $plan_re  = qr/1\.\.(\d+)/;
    my $test_re  = qr/(?:not )?ok/;
    my $failed;
    my $core_tap = '';
    foreach ( split "\n" => $tap ) {
        if (/^not ok/) {    # TODO tests are not failures
            $failed++
              unless m/^ ( [^\\\#]* (?: \\. [^\\\#]* )* )
                 \# \s* TODO \b \s* (.*) $/ix
        }
        $core_tap .= "$_\n" if /^(?:$plan_re|$test_re)/;
    }
    my $plan;
    if ( $core_tap =~ /^$plan_re/ or $core_tap =~ /$plan_re$/ ) {
        $plan = $1;
    }
    return 'No plan found'                     unless defined $plan;
    return "Failed $failed out of $plan tests" if $failed;

    my $plans_found = 0;
    $plans_found++ while $core_tap =~ /^$plan_re/gm;
    return "$plans_found plans found" if $plans_found > 1;

    my $tests = 0;
    $tests++ while $core_tap =~ /^$test_re/gm;
    return "Planned $plan tests and found $tests tests" if $tests != $plan;

    return;
}