#!perl
# Copyright (C) 2001-2005, The Perl Foundation.
# $Id: file.t 23187 2007-11-28 15:34:28Z kjs $
use strict;
use warnings;
use lib qw( . lib ../lib ../../lib );
use File::Spec;
use Test::More;
use Parrot::Config;
use Parrot::Test tests => 13;
=head1 NAME
syn/file.t - test inclusion of files
=head1 SYNOPSIS
A test script which is supposed to be called by Test::Harness.
=cut
use 5;
# Do not assume that . is in $PATH
my $PARROT = ".$PConfig{slash}parrot$PConfig{exe}";
my $PERL5 = $PConfig{perl};
my $ended_ok = 0;
delete_temp_files();
##############################
open my $FOO, '>', "temp.pasm" or die "Can't write temp.pasm\n";
print $FOO <<'ENDF';
.constant BAR 42
ENDF
close $FOO;
pir_output_is( <<'CODE', <<'OUT', 'include pasm' );
.sub test :main
print "before\n"
.include "temp.pasm"
print .BAR
print "\nafter\n"
end
.end
CODE
before
42
after
OUT
unlink 'temp.pasm';
##############################
open $FOO, '>', 'temp.pir' or die "Can't write temp.pir: $!\n";
print $FOO <<'ENDF';
.const int BAR = 42
ENDF
close $FOO;
pir_output_is( <<'CODE', <<'OUT', 'include pir' );
.sub test :main
print "before\n"
.include "temp.pir"
print BAR
print "\nafter\n"
end
.end
CODE
before
42
after
OUT
unlink "temp.pir";
##############################
open $FOO, '>', 'temp.inc' or die "Can't write temp.inc: $!\n";
print $FOO <<'ENDF';
.const int BAR = 42
ENDF
close $FOO;
pir_output_is( <<'CODE', <<'OUT', 'include temp.inc' );
.sub test :main
print "before\n"
.include "temp.inc"
print BAR
print "\nafter\n"
end
.end
CODE
before
42
after
OUT
unlink "temp.inc";
##############################
my $file = '_test.inc';
open my $F, '>', $file or die "Can't create $file: $!\n";
print $F <<'EOF';
.sub _foo # sub foo(int a, int b)
.param int a
.param int b
print "a = "
print a
print "\n"
print "b = "
print b
print "\n"
.local int pl
.local int mi
pl = a + b
mi = a - b
.return (pl, mi)
.end
EOF
close $F;
pir_output_is( <<'CODE', <<'OUT', 'subroutine in external file' );
.sub test :main
.local int x
x = 10
.const int y = 20
.local int r
.local int s
(r, s) = _foo(x,y)
print "r = "
print r
print "\n"
print "s = "
print s
print "\n"
end
.end
.include "_test.inc"
CODE
a = 10
b = 20
r = 30
s = -10
OUT
# test load_bytecode branches and subs
# write sub2
open $FOO, '>', 'temp.pir' or die "Can't write temp.pir: $!\n";
print $FOO <<'ENDF';
.sub _sub2
print "sub2\n"
end
.end
ENDF
close $FOO;
# compile it
system_or_die( $PARROT, qw( -o temp.pbc temp.pir ) );
pir_output_is( <<'CODE', <<'OUT', 'call sub in external pbc' );
.sub _sub1
print "sub1\n"
load_bytecode "temp.pbc"
print "loaded\n"
$P0 = global "_sub2"
.begin_call
.call $P0
ret:
.end_call
end
.end
CODE
sub1
loaded
sub2
OUT
# write sub2
open $FOO, '>', 'temp.pir' or die "Can't write temp.pir: $!\n";
print $FOO <<'ENDF';
.sub _sub2
print "sub2\n"
.begin_return
.end_return
end
.end
ENDF
close $FOO;
# compile it
system_or_die( $PARROT, qw( -o temp.pbc temp.pir ) );
pir_output_is( <<'CODE', <<'OUT', 'call sub in external pbc, return' );
.sub _sub1
print "sub1\n"
load_bytecode "temp.pbc"
print "loaded\n"
$P0 = global "_sub2"
.begin_call
.call $P0
ret:
.end_call
print "back\n"
end
.end
CODE
sub1
loaded
sub2
back
OUT
# write sub2
open $FOO, '>', 'temp.pir' or die "Can't write temp.pir: $!\n";
print $FOO <<'ENDF';
.sub _not_sub2
print "not sub2\n"
end
.end
.sub _sub2
print "sub2\n"
end
.end
ENDF
close $FOO;
# compile it
system("$PARROT -o temp.pbc temp.pir");
pir_output_is( <<'CODE', <<'OUT', 'call sub in external pbc with 2 subs' );
.sub _sub1
print "sub1\n"
load_bytecode "temp.pbc"
print "loaded\n"
$P0 = global "_sub2"
.begin_call
.call $P0
ret:
.end_call
end
.end
CODE
sub1
loaded
sub2
OUT
# write sub2
open $FOO, '>', "temp.pir" or die "Can't write temp.pir: $!\n";
print $FOO <<'ENDF';
.sub _sub2
print "sub2\n"
.begin_return
.end_return
end
.end
ENDF
close $FOO;
# compile it
pir_output_is( <<'CODE', <<'OUT', 'call sub in external pir, return' );
.sub _sub1
print "sub1\n"
load_bytecode "temp.pir"
print "loaded\n"
$P0 = global "_sub2"
.begin_call
.call $P0
ret:
.end_call
print "back\n"
end
.end
CODE
sub1
loaded
sub2
back
OUT
pir_output_is( <<'CODE', <<'OUT', 'call internal sub like external' );
.sub _sub1
print "sub1\n"
$P0 = global "_sub2"
.begin_call
.call $P0
ret:
.end_call
print "back\n"
end
.end
.sub _sub2
print "sub2\n"
.begin_return
.end_return
end
.end
CODE
sub1
sub2
back
OUT
# write subs
open $FOO, '>', 'temp.pir' or die "Can't write temp.pir: $!\n";
print $FOO <<'ENDF';
.sub _sub1
print "sub1\n"
$P0 = global "_sub2"
.begin_call
.call $P0
ret:
.end_call
print "back\n"
end
.end
.sub _sub2
print "sub2\n"
.begin_return
.end_return
end
.end
ENDF
close $FOO;
# compile it
system_or_die( $PARROT, qw( -o temp.pbc temp.pir ) );
use Test::More;
is( `$PARROT temp.pbc`, <<OUT, 'call internal sub like external, precompiled' );
sub1
sub2
back
OUT
{
# include a non-existent file and catch the error message
my $err_msg;
{
open $FOO, '>', 'temp.pir' or die "Can't write temp.pir: $!\n";
print $FOO <<'END_PIR';
# Including a non-existent file should produce an error
.include "non_existent.pir"
# An error should have been raised
.sub test :main
# dummy, because a main function is expected
end
.end
END_PIR
close $FOO;
my $OLDERR;
open $OLDERR, '>&', 'STDERR' or die "Can't save STDERR: $!\n";
open STDERR, '>', 'temp.out' or die "Can't write temp.out: $!\n";
system( $PARROT, 'temp.pir' ); # We expect an error here.
open $FOO, '<', 'temp.out' or die "Can't read temp.out: $!\n";
{ local $/; $err_msg = <$FOO>; }
close $FOO;
open STDERR, '>&', $OLDERR or die "Can't restore STDERR: $!\n";
unlink 'temp.out';
}
# read a non-existent file and catch the error message
my $enoent_err_msg;
{
open $FOO, '<', 'non_existent.file';
my $ENOENT = $! + 0;
open $FOO, '>', 'temp.pir' or die "Can't write temp.pir: $!\n";
print $FOO <<"END_PIR";
.sub test \:main
# run a OS command, and get the errmessge for the exit code
.local string enoent_err_msg
err enoent_err_msg, $ENOENT
print enoent_err_msg
end
.end
END_PIR
close $FOO;
$enoent_err_msg = qx{$PARROT temp.pir}
}
$err_msg =~ s/\r//g if $^O =~ /^(MSWin32|msys)$/i;
is( $err_msg, << "OUT", 'including a non-existent file' );
error:imcc:$enoent_err_msg
\tin file 'temp.pir' line 2
OUT
unlink 'temp.pir';
}
SKIP:
{
skip( 'multiple loading not speced - failing', 1 );
pir_output_is( <<'CODE', <<'OUT', 'twice call sub in external pir, return' );
.sub _sub1
print "sub1\n"
load_bytecode "temp.pir"
print "loaded\n"
$P0 = global "_sub2"
.begin_call
.call $P0
ret:
.end_call
print "back\n"
print "sub1 again\n"
load_bytecode "temp.pir"
print "loaded again\n"
$P0 = global "_sub2"
.begin_call
.call $P0
ret_again:
.end_call
print "back again\n"
end
.end
CODE
sub1
loaded
sub2
back
sub1 again
loaded again
sub2
back again
OUT
}
my @temp_files;
SKIP:
{
my $temp_dir = File::Spec->tmpdir();
my $td2 = File::Spec->catfile( $temp_dir, '.' );
substr( $td2, -1, 1, '' );
for my $file (qw( with_slash without_slash )) {
push @temp_files, File::Spec->catfile( $temp_dir, "${file}.pir" );
open( my $out_fh, '>', $temp_files[-1] )
or skip( "Cannot write temporary file to $temp_files[-1]", 2 );
print {$out_fh} <<"TEMP_PIR";
.sub $file
print "$file() called!\\n"
.end
TEMP_PIR
}
pir_output_is( <<"CODE", <<'OUT', 'load PIR from added paths, minding slash' );
.include 'iglobals.pasm'
.sub main :main
.local pmc interp
getinterp interp
.local pmc lib_paths
lib_paths = interp[.IGLOBALS_LIB_PATHS]
# XXX - hard-coded magic constant (should be PARROT_LIB_PATH_LIBRARY)
.local pmc include_paths
include_paths = lib_paths[1]
unshift include_paths, '$temp_dir'
load_bytecode 'with_slash.pir'
.local pmc dummy
dummy = shift include_paths
unshift include_paths, '$td2'
load_bytecode 'without_slash.pir'
with_slash()
without_slash()
.end
CODE
with_slash() called!
without_slash() called!
OUT
}
$ended_ok = 1;
sub system_or_die {
my @args = @_;
print "# Running @args\n";
my $rc = system(@args);
if ( $rc != 0 ) {
die "Couldn't run: @args\n";
}
print "# Return $rc\n";
}
sub delete_temp_files {
for ( @temp_files, $file, 'temp.pir', 'temp.pbc' ) {
unlink if defined;
}
}
END {
delete_temp_files() if $ended_ok;
}
# Local Variables:
# mode: cperl
# cperl-indent-level: 4
# fill-column: 100
# End:
# vim: expandtab shiftwidth=4:
syntax highlighted by Code2HTML, v. 0.9.1