Compare commits

..

8 Commits
main ... main

5 changed files with 169 additions and 132 deletions

View File

@ -3,10 +3,10 @@ use Module::Build;
my $home = $ENV{HOME};
my $build = Module::Build->new(
module_name => 'Owl::TestRunner',
module_name => 'LPSC::Builder',
license => 'GPLv3',
dist_author => 'Sergio Iglesias <contact@owlcode.tech>',
dist_abstract => 'A test runner for Perl',
dist_abstract => 'A build system for LPSC',
requires => {
'Path::Tiny' => 0,
'Types::Standard' => 0,

View File

@ -1,3 +1,38 @@
# OwlTestRunner
A test runner for it's usage for testing C.
A test runner for it's usage for testing C.
## Requirements
### Gentoo
```shell
sudo emerge -a sys-libs/db
```
### Debian-like
```shell
sudo apt update
sudo apt install libdb-dev build-essentials libcpanplus-dist-build-perl
```
## Installing
Clone this repo and cd into the cloned directory and run:
```shell
cpan .
```
If it is the first time using cpan it will prompt you to some questions about
how do you want to setup cpan.
If you choose local::lib, after answering them restart your shell or
source ~/.bashrc, if using a non-bash shell you may have to add manually the
appropiate environment variables to your shell's rc, you can get those by issuing the
following command:
```shell
PERL5LIB="$HOME/perl5/lib/perl5" perl -Mlocal::lib
```

7
lib/LPSC/Builder.pm Normal file
View File

@ -0,0 +1,7 @@
package LPSC::Builder v0.0.1;
use v5.30.0;
use strict;
use warnings;
1;

View File

@ -0,0 +1,124 @@
package LPSC::Builder::TestRunner;
use v5.30.0;
use strict;
use warnings;
use DB_File;
use Params::ValidationCompiler qw/validation_for/;
use Types::Standard qw/ArrayRef Str Bool/;
use Getopt::Long::Descriptive;
use Path::Tiny qw/path/;
use Capture::Tiny qw/tee_merged/;
use Term::ANSIColor qw/color/;
my $db_file = path($0)->parent->child('test.db');
my @errors;
my $ERROR_CODE_SOME_TEST_FAILED = 500;
{
my $validator = validation_for(
params => {
test_files => {
type => ArrayRef [Str],
},
clean => {
type => Bool,
},
halt => {
type => Bool,
},
}
);
sub new {
my $class = shift;
my $self = bless {}, $class;
my %params = $validator->(@_);
my $test_files = $params{test_files};
$self->{test_files} = [@$test_files];
$self->_options->{halt} = $params{halt};
$self->_options->{clean} = $params{clean};
return $self;
}
}
sub _options {
my $self = shift;
if ( !defined $self->{options} ) {
$self->{options} = {};
}
return $self->{options};
}
sub run {
my $self = shift;
if ( $self->_options->{clean} ) {
my %test_files_success_status;
tie %test_files_success_status, 'DB_File', $db_file;
%test_files_success_status = ();
untie %test_files_success_status;
}
for my $test_file ( @{ $self->{test_files} } ) {
if ( $self->_test_already_succeded($test_file) ) {
say omited() . "$test_file last test was successful.";
next;
}
my $return_code;
my ($merged) = tee_merged {
$return_code = system $test_file;
};
my %test_files_success_status;
tie %test_files_success_status, 'DB_File', $db_file;
$test_files_success_status{$test_file} = !$return_code;
if ($return_code) {
push @errors, error() . "File $test_file\n" . $merged;
if ( $self->_options->{halt} ) {
$self->show_errors;
}
}
}
$self->show_errors;
}
sub show_errors {
for my $error (@errors) {
say $error;
}
if (@errors) {
exit $ERROR_CODE_SOME_TEST_FAILED;
}
exit 0;
}
sub omited {
return color('blue') . '[[OMITED]] ' . reset_color();
}
sub error {
return color('red') . '[[ERROR]] ' . reset_color();
}
sub reset_color {
return color('reset');
}
sub _test_already_succeded {
my $self = shift;
my $test = shift;
my %test_files_success_status;
tie %test_files_success_status, 'DB_File', $db_file;
return $test_files_success_status{$test};
}
1;

View File

@ -1,129 +0,0 @@
package Owl::TestRunner v0.0.1;
use v5.30.0;
use strict;
use warnings;
use DB_File;
use Params::ValidationCompiler qw/validation_for/;
use Types::Standard qw/ArrayRef Str/;
use Getopt::Long::Descriptive;
use Path::Tiny qw/path/;
use Capture::Tiny qw/tee_merged/;
use Term::ANSIColor qw/color/;
my $db_file = path($0)->parent->child('test.db');
my %test_files_success_status;
tie %test_files_success_status, 'DB_File', $db_file;
my @errors;
my $ERROR_CODE_SOME_TEST_FAILED = 500;
{
my $validator = validation_for(
params => {
test_files => {
type => ArrayRef [Str],
}
}
);
sub new {
my $class = shift;
my $self = bless {}, $class;
my %params = $validator->(@_);
my $test_files = $params{test_files};
$self->{test_files} = [@$test_files];
return $self;
}
}
sub _options {
my $self = shift;
if ( !defined $self->{options} ) {
$self->{options} = {};
$self->_getopt;
}
return $self->{options};
}
sub _getopt {
my $self = shift;
my ($opt, $usage) = describe_options(
'./test_runner.pl %o',
[ 'clean|c', "Cleans the previously succeded tests", ],
[ 'halt|h', "Halts on error", ],
[],
[ 'help', "print usage message and exit", { shortcircuit => 1 } ],
);
print($usage->text), die if $opt->help;
my $options = $self->_options;
$options->{halt} = $opt->halt;
$options->{clean} = $opt->clean;
}
sub run {
my $self = shift;
if ($self->_options->{clean}) {
%test_files_success_status = ();
}
for my $test_file (@{$self->{test_files}}) {
if ($self->_test_already_succeded($test_file)) {
say omited() . "$test_file last test was successful.";
next;
}
my $return_code;
my ($merged) = tee_merged {
$return_code = system $test_file;
};
$test_files_success_status{$test_file} = !$return_code;
if ($return_code) {
push @errors, error() . "File $test_file\n" . $merged;
if ($self->_options->{halt}) {
$self->show_errors;
}
}
}
$self->show_errors;
}
sub show_errors {
for my $error (@errors) {
say $error;
}
if (@errors) {
exit $ERROR_CODE_SOME_TEST_FAILED;
}
exit 0;
}
sub omited {
return color('blue').'[[OMITED]] '.reset_color();
}
sub error {
return color('red').'[[ERROR]] '.reset_color();
}
sub reset_color {
return color('reset');
}
sub _test_already_succeded {
my $self = shift;
my $test = shift;
return $test_files_success_status{$test};
}
1;