Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you test exec used with indirect object syntax?

What's the best way to test my Perl script which calls exec with indirect object syntax? Is there a way to mock exec that doesn't lead to a syntax error? Do I have to move exec to a wrapper function that only calls exec and mock that function? Or is there another way to test the script?

Chapter 5 of Perl Testing - A Developer's Notebook has an example on Overriding Built-ins where they overwrite system to test a module. I would like to do the same to test exec, but in the indirect object syntax.

exec.pl (with indirect object syntax)

package Local::Exec;

use strict;
use warnings;

main() if !caller;

sub main {
    my $shell = '/usr/bin/ksh93';
    my $shell0 = 'ksh93';

    # launch a login shell
    exec {$shell} "-$shell0";
    return;
}

1;

exec.t

#!perl

use strict;
use warnings;

use Test::More;

require_ok('./exec.pl');

package Local::Exec;
use subs 'exec';
package main;

my @exec_args;

*Local::Exec::exec = sub {
    @exec_args = @_;
    return 0;
};

is(Local::Exec::main(), undef, 'main() returns undef');
is_deeply(\@exec_args, [ '/usr/bin/ksh93' ], 'exec() was called with correct arguments');

done_testing;

prove -vt exec.t

This does not work, my exec doesn't work with the indirect object syntax, where the built-in does.

$ prove -vt exec.t
exec.t .. String found where operator expected at ./exec.pl line 15, near "} "-$shell0""
        (Missing operator before  "-$shell0"?)

not ok 1 - require './exec.pl';
#   Failed test 'require './exec.pl';'
#   at exec.t line 8.
#     Tried to require ''./exec.pl''.
#     Error:  syntax error at ./exec.pl line 15, near "} "-$shell0""
# Compilation failed in require at (eval 6) line 2.
Undefined subroutine &Local::Exec::main called at exec.t line 21.
# Tests were run but no plan was declared and done_testing() was not seen.
# Looks like your test exited with 255 just after 1.
Dubious, test returned 255 (wstat 65280, 0xff00)
Failed 1/1 subtests

Test Summary Report
-------------------
exec.t (Wstat: 65280 Tests: 1 Failed: 1)
  Failed test:  1
  Non-zero exit status: 255
  Parse errors: No plan found in TAP output
Files=1, Tests=1,  1 wallclock secs ( 0.02 usr  0.01 sys +  0.04 cusr  0.01 csys =  0.08 CPU)
Result: FAIL

exec.pl (without indirect object syntax)

package Local::Exec;

use strict;
use warnings;

main() if !caller;

sub main {
    my $shell = '/usr/bin/ksh93';

    exec $shell;
    return;
}

1;

prove -vt exec.t

Just for reference, this works:

$ prove -vt exec.t
exec.t ..
ok 1 - require './exec.pl';
ok 2 - main() returns undef
ok 3 - exec() was called with correct arguments
1..3
ok
All tests successful.
Files=1, Tests=3,  0 wallclock secs ( 0.02 usr  0.01 sys +  0.04 cusr  0.01 csys =  0.08 CPU)
Result: PASS
like image 822
Sven Kirmess Avatar asked Dec 07 '25 05:12

Sven Kirmess


1 Answers

Replace

exec { $shell } "-$shell0";

with

sub _exec(&@) {
   my $prog_cb = shift;
   exec { $prog_cb->() } @_
}

_exec { $shell } "-$shell0"

Then your test can replace _exec.

like image 133
ikegami Avatar answered Dec 09 '25 00:12

ikegami



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!