perlquestion
pokki
<p>Wise monks,</p>
<p>I'm in the process of writing a module to test shell sessions using IPC::Run, and I've hit the hurdle described in the subject line:
I can't manage to make cd work.</p>
<p>I tried various things until I reread the IPC::Run documentation
which states "No support for cd, setenv, or export: do these in an
init() sub (example follows)". Okay, but I don't just need cd once to
put my script in the right directory, I need a fully interactive
session that accepts any command. (Does anyone know why this
limitation exists, by the way?)</p>
<p> If you're curious, this is the kind of tool you feed an
almost-but-not-quite shell script with the expected output after every
command. Then the tool runs every command and compares the output.
This is highly useful for teaching material when you need to
demonstrate how, e.g., a DVCS works (if you've
used <a href="https://bitheap.org/cram/">Cram</a> before, the example
will look rather familiar):</p>
<spoiler>
<code>
#!/bin/bash
# Do all the work in /tmp
$ cd /tmp
# Testing presence of Mercurial
$ hg --version
re: Mercurial Distributed SCM \(version [\d.]+\)
(see http://mercurial.selenic.com for more information)
re: Copyright \(C\) [\d-]+ Matt Mackall and others
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# Creating a repository
$ mkdir foo
$ cd foo
$ pwd
/tmp/foo
$ hg init
$ echo "this is a file" > content
$ cat content
this is a file
$ hg add content
$ hg st
A content
$ hg commit -m "created repo and added a file"
# Checking that everything looks good
$ hg log
re: changeset: 0:[a-f0-9]{12}
tag: tip
user: Fabrice Gabolde <fabrice.gabolde@uperto.com>
re: date: .*
summary: created repo and added a file
</code>
<p>Lines starting with $ are shell commands, the others are expected
output. There are facilities for globs/regexes, comments,
etc (not everything demonstrated here). The file above gives me:</p>
<code>
# cd /tmp
# hg --version
ok 1 - regex match of 'Mercurial Distributed SCM \(version [\d.]+\)'
ok 2 - literal match of '(see http://mercurial.selenic.com for more information)'
ok 3 - literal match of ''
ok 4 - regex match of 'Copyright \(C\) [\d-]+ Matt Mackall and others'
ok 5 - literal match of 'This is free software; see the source for copying conditions. There is NO'
ok 6 - literal match of 'warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.'
# mkdir foo
# cd foo
# pwd
not ok 7 - literal match of '/tmp/foo'
# Failed test 'literal match of '/tmp/foo''
# at lib/Lembas.pm line 87.
# got: '/home/fgabolde/work/Lembas'
# expected: '/tmp/foo'
# hg init
# echo "this is a file" > content
# cat content
# STDERR: cat: content
# STDERR: : No such file or directory
</code>
<p>... and it all goes downhill from there, because there are other
issues with the code. (The full script is there just to show people
what I'm working on and hopefully garner criticism as a side-effect;
in reality I have a test on pwd right after cd /tmp and it fails as
well.) The foo directory doesn't seem to be created anywhere (says find / -iname foo) either, but cd or mkdir don't complain at all (like cat does at the end)</p>
</spoiler>
<p>I'm using IPC::Run basically like this (shortened):</p>
<code>
my ($input, $output, $errput);
my $subprocess = start([ '/bin/bash' ],
'<', \$input,
'1>pty>', \$output,
'2>', \$errput);
# later, for each $command { shell => 'pwd', 'outputs' => [ '/tmp/foo' ] }
diag $command->{shell};
$input = $command->{shell} . "\n";
foreach my $expected_output (@{$command->{outputs}}) {
while ($output !~ /\n/) {
if ($errput) {
diag 'STDERR: '.$errput;
$errput = '';
}
$subprocess->pump;
}
# munge $expected_output and compare stuff
}
</code>
<p>Does anyone automate shell(or other CLI apps) sessions to this degree? With what module? Looking around on CPAN it seems only IPC::Run really does the whole "talk to a subprocess double-pipe style" hog. I don't get why bash seems to "reset" between every command, though. Did I miss something really obvious?</p>