Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unexpected output executing a package function

Tags:

raku

I have the following dir structure (simplified version to reproduce the issue):

testing/
  lib/
   CLI.pm6
  t/
    01-test.t

You can check the source here. The problem is that if you run raku -Ilib t/01-test.t you will get the following output:

    ok 1 - show help message
    1..1
ok 1 - no arguments provided
    not ok 1 - long version
    # Failed test 'long version'
    # at site#sources\D2E3739A3B53AD1F7CFEE6DA262613FD174A0BC9 (Test::Output) line 84
    # expected a match with: /Documentable\sversion/
    #                   got: "version\r\n"
    1..1
    # You failed 1 test of 1
not ok 2 - version command
# Failed test 'version command'
# at t\01-test.t line 12
1..2
# You failed 1 test of 2
Execute "documentable --help" for more information.

Everything seems normal (obviously tests are failing). The problem is the last line:

Execute "documentable --help" for more information.

That line is added by CLI::MAIN(), but is not executed after the tests have finished. You can even comment the first subtest block and it will still appear. This is causing a failed execution of the tests using prove6 -l. Any idea what's going on?

like image 514
Antonio Gamiz Delgado Avatar asked Jun 25 '20 09:06

Antonio Gamiz Delgado


1 Answers

Change use CLI; to use CLI {}.

The problem

Presuming the CLI package is found, running this:

use CLI;

will display:

Execute "documentable --help" for more information.

Unexpected output

The above is clearly not what you want, but your testing code doesn't alter how the CLI package is used. So the unwanted message should be expected because it is the MAIN feature working as it is supposed to.[1]

A solution

Your question boils down to something like:

How do I use a package with exported MAINs while suppressing the automatic running of those MAINs?

One simple solution is to not import MAIN (or rather &MAIN[2].)

One way to do that is to replace the use CLI; with use CLI {}.

A use CLI; statement is equivalent to use CLI :DEFAULT;. (The :DEFAULT tag picks up everything that has an is export on it without some different tag.)

If you write use CLI {} instead then no symbols will be imported other than CLI itself, which will be bound to the symbols that CLI exports in their package qualified form.

This way your manual tests of MAIN (which specify the package -- CLI::MAIN) will continue to work, but automatic invocation of it will be suppressed.

Footnotes

[1] In case the doc doesn't make things clear:

  • The is export on the our proto MAIN declaration in the CLI package exports a &MAIN[2]symbol;

  • The use statement imports that &MAIN symbol into t/01-test.t's lexical scope;

  • The command raku ... t/01-test.t invokes t/01-test.t without arguments, as does prove6 -l ... (assuming no additional arguments beyond the lib are passed to the mainline). So a zero argument &MAIN call is invoked;

  • The zero argument call resolves to the zero parameter multi MAIN() { note 'Execute ... information'; } declaration. So you see its message.

[2] A sub declaration like MAIN declares a symbol &MAIN. (And a sub call like MAIN blah blah calls the routine associated with &MAIN.)

like image 134
raiph Avatar answered Sep 22 '22 12:09

raiph