From 1bfe73f77a1af84744299d6c3d38a78aac01f17c Mon Sep 17 00:00:00 2001 From: Nathan McCarty Date: Tue, 31 Dec 2024 16:28:24 +0000 Subject: [PATCH 1/3] Rename regex module --- META6.json | 2 +- bin/iutils | 2 +- lib/IUtils/{Comments.rakumod => Regexes.rakumod} | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) rename lib/IUtils/{Comments.rakumod => Regexes.rakumod} (91%) diff --git a/META6.json b/META6.json index c3f0ccb..8b12ce9 100644 --- a/META6.json +++ b/META6.json @@ -12,7 +12,7 @@ "provides": { "IUtils": "lib/IUtils.rakumod", "IUtils::IDEMode": "lib/IUtils/IDEMode.rakumod", - "IUtils::Comments": "lib/IUtils/Comments.rakumod" + "IUtils::Regexs": "lib/IUtils/Regexes.rakumod" }, "bin": { "iutils": "bin/iutils" diff --git a/bin/iutils b/bin/iutils index 9f99a00..a0586bd 100755 --- a/bin/iutils +++ b/bin/iutils @@ -1,7 +1,7 @@ #!/usr/bin/env raku use v6.d; use IUtils; -use IUtils::Comments; +use IUtils::Regexes; #| Execute the tests in an idris project multi MAIN( diff --git a/lib/IUtils/Comments.rakumod b/lib/IUtils/Regexes.rakumod similarity index 91% rename from lib/IUtils/Comments.rakumod rename to lib/IUtils/Regexes.rakumod index edd7e9d..ebcfb03 100644 --- a/lib/IUtils/Comments.rakumod +++ b/lib/IUtils/Regexes.rakumod @@ -1,4 +1,4 @@ -unit module IUtils::Comments; +unit module IUtils::Regexes; my token comment-start { \- \- } my token type { From 49c118eef44315332d944d23ab0e70ed19ccfa8b Mon Sep 17 00:00:00 2001 From: Nathan McCarty Date: Tue, 31 Dec 2024 16:30:53 +0000 Subject: [PATCH 2/3] Refactor compiler interaction --- META6.json | 3 +- lib/IUtils.rakumod | 71 ------------------------------------ lib/IUtils/Compiler.rakumod | 72 +++++++++++++++++++++++++++++++++++++ 3 files changed, 74 insertions(+), 72 deletions(-) create mode 100644 lib/IUtils/Compiler.rakumod diff --git a/META6.json b/META6.json index 8b12ce9..0918894 100644 --- a/META6.json +++ b/META6.json @@ -12,7 +12,8 @@ "provides": { "IUtils": "lib/IUtils.rakumod", "IUtils::IDEMode": "lib/IUtils/IDEMode.rakumod", - "IUtils::Regexs": "lib/IUtils/Regexes.rakumod" + "IUtils::Regexs": "lib/IUtils/Regexes.rakumod", + "IUtils::Compiler": "lib/IUtils/Compiler.rakumod" }, "bin": { "iutils": "bin/iutils" diff --git a/lib/IUtils.rakumod b/lib/IUtils.rakumod index d41c8f8..d6d896d 100644 --- a/lib/IUtils.rakumod +++ b/lib/IUtils.rakumod @@ -37,74 +37,3 @@ sub scan-packages(--> Array[PackageInfo:D]) is export { paths(:file(*.ends-with(".ipkg"))).map(*.IO.&scan-ipkg); return @ipkgs; } - - -# Utility functions for pack - -#| Invoke a pack command -sub pack-run(*@cmd) is export { - my $proc = run "pack", @cmd, :out, :err; - my $out = $proc.out.slurp(:close); - my $err = $proc.err.slurp(:close); - unless $proc { - die qq:to/END/; - Pack Failure! - Captured Output: - $out - - Captured StdErr: - $err - END - } -} - -#| Build a package with pack -sub pack-build($pkg) is export { - pack-run 'build', $pkg -} - -#| Test a package with pack -sub pack-test($pkg) is export { - pack-run 'build', $pkg -} - -#| Clean a package with pack -sub pack-clean($pkg) is export { - pack-run 'clean', $pkg -} - -# Utility functions for idris - -#| An error coming from the idris compiler -class IdrisError is Exception { - has Str $.out; - has Str $.err; - has Int $.exit-code; - has Str $.command; - - method message { - qq:to/END/; - Error running idris command: $.command - Command exited with $.exit-code - END - } -} - -#| Invoke an idris command -sub idris-run(*@cmd) is export { - my $proc = run "idris2", @cmd, :out, :err; - my $out = $proc.out.slurp(:close); - my $err = $proc.err.slurp(:close); - unless $proc { - IdrisError.new( - out => $out, err => $err, - exit-code => $proc.exitcode, command => @cmd.Str) - .throw; - } - return $out; -} - -#| Exec the expression with the given name in the given file -sub idris-exec($expr, $file) is export { - idris-run '--find-ipkg', '--exec', $expr, $file -} diff --git a/lib/IUtils/Compiler.rakumod b/lib/IUtils/Compiler.rakumod new file mode 100644 index 0000000..d8bfcba --- /dev/null +++ b/lib/IUtils/Compiler.rakumod @@ -0,0 +1,72 @@ +#| Utilities for interacting with the idris compiler and package manager +unit module IUtils::Compiler; + +# Utility functions for pack + +#| Invoke a pack command +sub pack-run(*@cmd) is export { + my $proc = run "pack", @cmd, :out, :err; + my $out = $proc.out.slurp(:close); + my $err = $proc.err.slurp(:close); + unless $proc { + die qq:to/END/; + Pack Failure! + Captured Output: + $out + + Captured StdErr: + $err + END + } +} + +#| Build a package with pack +sub pack-build($pkg) is export { + pack-run 'build', $pkg +} + +#| Test a package with pack +sub pack-test($pkg) is export { + pack-run 'build', $pkg +} + +#| Clean a package with pack +sub pack-clean($pkg) is export { + pack-run 'clean', $pkg +} + +# Utility functions for idris + +#| An error coming from the idris compiler +class IdrisError is Exception { + has Str $.out; + has Str $.err; + has Int $.exit-code; + has Str $.command; + + method message { + qq:to/END/; + Error running idris command: $.command + Command exited with $.exit-code + END + } +} + +#| Invoke an idris command +sub idris-run(*@cmd) is export { + my $proc = run "idris2", @cmd, :out, :err; + my $out = $proc.out.slurp(:close); + my $err = $proc.err.slurp(:close); + unless $proc { + IdrisError.new( + out => $out, err => $err, + exit-code => $proc.exitcode, command => @cmd.Str) + .throw; + } + return $out; +} + +#| Exec the expression with the given name in the given file +sub idris-exec($expr, $file) is export { + idris-run '--find-ipkg', '--exec', $expr, $file +} From 9bd0cc323f3dc800ab5d0331d8c2746d003596d9 Mon Sep 17 00:00:00 2001 From: Nathan McCarty Date: Tue, 31 Dec 2024 19:11:46 +0000 Subject: [PATCH 3/3] 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+) +}