#!/usr/bin/env perl
use strict;
use utf8;
use v5.10;

use File::Find qw(finddepth);
use Data::Dumper;
use Getopt::Long;
use FindBin;

my $help;
my $root;
my $list;
GetOptions(
    'h|help' => \$help,
    'r|root=s' => \$root,
    'l|list' => \$list,
);

if ($help) {
    say "Usage: $0 [options] target1 target2 ...";
    say "Options:";
    say "   -l,--list           list all tests";
    say "   -r,--root           directory with unittests";
    exit 0;
}

my $unittest_dir = (defined $root) ? $root : "$FindBin::Bin/../scripts/tests/unit";
$unittest_dir =~ s/\/$//;
say "Unittests dir: $unittest_dir";

if ($list) {
    my @all_tests = list_exec_recursive($unittest_dir);
    @all_tests = map {s/^$unittest_dir\/?//; s/\..+$//; $_} @all_tests;
    say "All tests:";
    print map {"\t$_\n"} @all_tests;
    exit 0;
}
my @targets = @ARGV;
if (!@targets) {
    say "no targets provided!";
    exit 1;
}

for my $target (@targets) {
    my @all_execs = list_exec_recursive($unittest_dir);
    my @target_execs = grep {/^$unittest_dir\/$target([\.\/])/} @all_execs;
    if (!@target_execs) {
        say "No tests for target '$target'";
        exit 0;
    }
    say "Tests for target '$target':";
    print map {"\t$_\n"} @target_execs;
    for my $target_exec (@target_execs) {
        my $name = $target_exec;
        $name =~ s/^$unittest_dir\/?//;
        say "Run test '$name'";
        system($target_exec);
        my $exit_code = $? >> 8;
        if ($exit_code) {
            exit($exit_code);
        }
    }
}

exit 0;

# aux
sub list_exec_recursive {
    # list all executable files in all subdirectories
    my $path = shift;

    my @files;
    finddepth(
        sub {
            return unless -f $_ and -X $_;
            push @files, $File::Find::name
        },
        $unittest_dir
    );
    return @files;
}
