5

It seems that variables in backticks are not expanded when passed onto the readpipe function. If I override the readpipe function, how do I expand variables?

BEGIN {
*CORE::GLOBAL::readpipe = sub {print "Run:@_\n"};
}

`ls /root`;
my $dir = "/var";
`ls $dir`;

Running this gives:

Run:ls /root
Run:ls $dir

I am trying to mock external calls for a test code that I am writing. If there is a CPAN module somewhere which can help in taking care of all this, that would help too.

Update:

I have decided to use a really ugly workaround to my problem. It turns out that using readpipe() instead of backticks expands variables correctly. I am using an automatic script cleaner before running my tests which converts all backticks to readpipe() before running the tests.

e.g Running:

$ cat t.pl

BEGIN {
    *CORE::GLOBAL::readpipe = sub {print "Run:@_\n"};
}

`ls /root`;
my $dir = "/var";
`ls $dir`;
readpipe("ls $dir");

Gives:

$ perl t.pl
Run:ls /root
Run:ls $dir
Run:ls /var

I am still looking out for a cleaner solution though.

Sandip Bhattacharya
  • 1,042
  • 10
  • 11

2 Answers2

3

That appears to be a bug in Perl. Use perlbug to report it.

ikegami
  • 367,544
  • 15
  • 269
  • 518
1

You probably want to use IPC::Run instead.

use IPC::Run 'run';

run [ "ls", $dir ], ">", \my $stdout or die "Cannot run - $!";

Or if you didn't want to capture the output, system() may be better

system( "ls", $dir ) == 0 or die "Cannot system - $!";
LeoNerd
  • 8,344
  • 1
  • 29
  • 36
  • 1
    Thanks for the module ref. I am however looking for an easy way to mock out system calls like backticks and system() to run my unittests of a legacy code. – Sandip Bhattacharya Jun 14 '12 at 10:17
  • @SandipBhattacharya i'm sure not i understand the issue. backticks and exec do not return any output while system does. would eval and qx fit the bill? – shinronin Jun 14 '12 at 15:19
  • @shinronin I am trying to override/mock backticks in existing legacy code so that I can test them safely. While I can replace the `*CORE::GLOBAL::readpipe` to mock backticks, they are not working in cases where the argument includes variables to be expanded. Because of this inconsistent behaviour between backticks and `readpipe()` it is difficult to mock such code. I am not trying to write new code. If I did, I would have used `readpipe()` instead of backticks so that I can mock out the code if I wish. – Sandip Bhattacharya Jun 14 '12 at 16:29
  • @shinronin: you've got that partially wrong; backticks *do* provide output, while system() is silent, and exec can't return output (because the process calling it is replaced). –  Jun 14 '12 at 23:13
  • @jeffbragg oops, true. I can never keep them straight. perldoc -f is a constant companion. ;-) – shinronin Jun 15 '12 at 11:44