unit sub MAIN(
  :a($author),
  :i($install),
  :$rmd,
  :$disable-spesh,
  :$disable-spesh-inline,
  :$disable-JIT,
  :$enable-spesh-nodelay,
  :$enable-spesh-blocking,
  :$enable-spesh-log,
);

say run(<raku --version>, :out).out.slurp.chomp;
say "Running on $*DISTRO.gist().\n";

if $rmd {
    %*ENV<RAKUDO_MODULE_DEBUG> := 1;
    say "RAKUDO_MODULE_DEBUG=1";
}

if $disable-spesh {
    %*ENV<MVM_SPESH_DISABLE> := 1;
    say "MVM_SPESH_DISABLE=1";
}

if $disable-spesh-inline {
    %*ENV<MVM_SPESH_INLINE_DISABLE> := 1;
    say "MVM_SPESH_INLINE_DISABLE=1";
}

if $disable-JIT {
    %*ENV<MVM_JIT_DISABLE> := 1;
    say "MVM_JIT_DISABLE=1";
}

if $enable-spesh-nodelay {
    %*ENV<MVM_SPESH_NODELAY> := 1;
    say "MVM_SPESH_NODELAY=1";
}

if $enable-spesh-blocking {
    %*ENV<MVM_SPESH_BLOCKING> := 1;
    say "MVM_SPESH_BLOCKING=1";
}

my $spesh-log;
if $enable-spesh-log {
    $spesh-log = (
      $enable-spesh-log ~~ Bool ?? "spesh-log" !! $enable-spesh-log
    ).IO;
    %*ENV<MVM_SPESH_LOG> := $spesh-log.absolute;
    say "MVM_SPESH_LOG=$spesh-log.relative()";
}

say ""
  if $rmd
  || $disable-spesh
  || $disable-spesh-inline
  || $disable-JIT
  || $enable-spesh-nodelay
  || $enable-spesh-blocking
  || $enable-spesh-log;

say "Testing {
    (try "dist.ini".IO.lines.head.substr(7)) // "..."
}{
    " including author tests" if $author
}";

my @failed;
my $done   = 0;

sub process($proc, $filename) {
    if $proc {
        $proc.out.slurp;
        $spesh-log.unlink if $spesh-log;
    }
    else {
        @failed.push($filename);
        if $proc.out.slurp -> $stdout {
            my @lines = $stdout.lines;
            with @lines.first(
              *.starts-with(" from gen/moar/stage2"),:k)
            -> $index {
                say @lines[^$index].join("\n");
            }
            else {
                say $stdout;
            }
        }
        else {
            say "No output received, exit-code $proc.exitcode() ($proc.signal()):\n$proc.os-error()";
        }

        if $spesh-log {
            say "\nSpesh log requested, showing last 20000 lines:";
            say $spesh-log.lines(:!chomp).tail(20000).join;
            $spesh-log.unlink;
        }
    }
}

sub install() {
    my $proc := run 'zef', "install", ".", "--verbose", "--/test", :out,:err,:merge;
    process($proc, "*installation*");
}

sub test-dir($dir) {
    my $io := $dir.IO;
    if $io.e && $io.d {
        for $io.dir(:test(*.ends-with: '.t' | '.rakutest')).map(*.Str).sort {
            say "=== $_";
            my $proc := run "raku", "--ll-exception", "-I.", $_, :out,:err,:merge;
            process($proc, $_);
            $done++;
        }
    }
}

test-dir("t");
if "t".IO.e {
    test-dir($_) for dir(
      "t", :test({ !.starts-with(".") && "t/$_".IO.d})
    ).map(*.Str).sort;
}
test-dir("xt") if $author;
if $install {
    install;
    ++$done;
}

if @failed {
    say "\nFAILED: {+@failed} of $done:";
    say "  $_" for @failed;
    exit +@failed;
}

say "\nALL {"$done " if $done > 1}OK";

# vim: expandtab shiftwidth=4
