From 9bd0cc323f3dc800ab5d0331d8c2746d003596d9 Mon Sep 17 00:00:00 2001 From: Nathan McCarty Date: Tue, 31 Dec 2024 19:11:46 +0000 Subject: [PATCH] Somewhat working test running --- bin/iutils | 41 +++++++++++++++++++++++++++++------ lib/IUtils.rakumod | 44 ++++++++++++++++++++++++++++++++++++++ lib/IUtils/Regexes.rakumod | 4 ++++ 3 files changed, 82 insertions(+), 7 deletions(-) diff --git a/bin/iutils b/bin/iutils index a0586bd..9c2671d 100755 --- a/bin/iutils +++ b/bin/iutils @@ -2,7 +2,9 @@ use v6.d; use IUtils; use IUtils::Regexes; +use IUtils::Compiler; +# TODO: Add filtering for tests based on module/name #| Execute the tests in an idris project multi MAIN( "test", @@ -12,13 +14,38 @@ multi MAIN( chdir($project-path.IO.resolve: :completely) if $project-path; # Scan for our packages my @packages = scan-packages; - # Collect tests - my @tests; - for @packages -> $package { - # FIXME - say 'Finding tests for ', $package.ipkg.relative; - for $package.sources -> $source { - say 'Scanning for tests in ', $source; + # Collect runables + my @runables = @packages.map: *.runnables; + # Run the tests + my $basedir = $*CWD; + for @runables -> $runable { + # Make sure the package is built + pack-build $runable.ipkg.relative; + # CD to the local directory to make sure idris can exec the expressions + indir $runable.ipkg.parent, { + next unless $runable.tests.elems > 0; + say "** Testing {$runable.ipkg.relative: $basedir}"; + for $runable.tests.keys -> $module-name { + my $module = $runable.tests{$module-name}; + next unless $module.tests.elems > 0; + say "-- Testing $module-name".indent(2); + for $module.tests -> $test { + try { + idris-exec $test, $module.source.relative; + } + if $! { + my $stdout = $1.err.lines.map(*.indent(8)).join("\n"); + say "+ $test: FAIL".indent(4); + say "stdout:".indent(6); + $!.err.lines.map(*.indent(8)).join("\n"); + say "stderr:".indent(6); + $!.err.lines.map(*.indent(8)).join("\n"); + say "exit code: {$!.exit-code}" + } else { + say "+ $test: Pass".indent(4); + } + } + } } } } diff --git a/lib/IUtils.rakumod b/lib/IUtils.rakumod index d6d896d..9d7f1df 100644 --- a/lib/IUtils.rakumod +++ b/lib/IUtils.rakumod @@ -3,8 +3,29 @@ unit module IUtils; need IUtils::IDEMode; +use IUtils::Regexes; + use paths; +#| Structure representing the tests in a module +class ModuleTests { + #| The name of this module + has Str:D $.name is required; + #| The source file of this module + has IO::Path:D $.source is required; + #| A list of the associated tests this module has + has Str:D @.tests is required; +} + +#| Structure representing all of the runables assocated with a project +class PackageRunables { + #| The ipkg for this project + has IO::Path:D $.ipkg is required; + # TODO: Add benchmarks + #| A map from the name of the module to a list of tests + has ModuleTests:D %.tests is required; +} + #| Structure representing the root of what idris considers a package directory, #| with the associated ipkg and source files. These can and will overlap within #| the same directory. @@ -12,6 +33,29 @@ class PackageInfo { has IO::Path:D $.ipkg is required; has IO::Path:D $.root is required; has IO::Path:D @.sources is required; + + method runnables { + # Locate the tests + my %tests = Hash.new; + for @.sources -> $source { + my $contents = $source.slurp; + if $contents ~~ &module-name { + my $module-name = $.Str; + my @tests; + for $contents.match(&flagged-expression, :g) -> $match { + @tests.push($match.Str); + } + if @tests.elems > 0 { + %tests{$module-name} = + ModuleTests.new(name => $module-name, + source => $source, + tests => @tests); + } + } + } + # Build and return the runnables + PackageRunables.new(ipkg => self.ipkg, tests => %tests) + } } #| Scan a particular ipkg for its associated sources diff --git a/lib/IUtils/Regexes.rakumod b/lib/IUtils/Regexes.rakumod index ebcfb03..2b9cc71 100644 --- a/lib/IUtils/Regexes.rakumod +++ b/lib/IUtils/Regexes.rakumod @@ -12,3 +12,7 @@ my regex flagged-expression is export { [<&comment-start> \V* \v]* \h+ \: \V* \v } + +my regex module-name is export { + 'module' \h* $=(\S+) +}