2 # Copyright (C) 2001-2010, Parrot Foundation.
7 t/perl/Parrot_Test.t - Parrot::Test unit tests
11 % prove t/perl/Parrot_Test.t
15 These tests cover the basic functionality of C<Parrot::Test>.
26 use IO::CaptureOutput qw| capture |;
27 use Parrot::Config '%PConfig';
30 eval "use Test::Builder::Tester;";
32 plan( skip_all => "Test::Builder::Tester not installed\n" );
38 use lib qw( . lib ../lib ../../lib );
41 my $pre_env = exists $ENV{PARROT_TEST} ? $ENV{PARROT_TEST} : undef;
42 use_ok('Parrot::Test') or die;
44 my $post_env = exists $ENV{PARROT_TEST} ? $ENV{PARROT_TEST} : undef;
45 if ( defined $pre_env ) {
46 is( $post_env, $pre_env, 'PARROT_TEST env unchanged' );
49 is( $post_env, 1, 'PARROT_TEST env set' );
53 can_ok( 'Parrot::Test', $_ ) for qw/
54 c_output_is c_output_isnt
55 c_output_like c_output_unlike
56 example_output_is example_output_isnt
58 example_error_output_is example_error_output_isnt
59 example_error_output_like
60 language_error_output_is language_error_output_isnt
61 language_error_output_like
62 language_output_is language_output_isnt
64 pasm_error_output_is pasm_error_output_isnt
65 pasm_error_output_like pasm_error_output_unlike
66 pasm_output_is pasm_output_isnt
67 pasm_output_like pasm_output_unlike
68 pbc_error_output_is pbc_error_output_isnt
69 pbc_error_output_like pbc_error_output_unlike
70 pbc_output_is pbc_output_isnt
71 pbc_output_like pbc_output_unlike
72 pir_error_output_is pir_error_output_isnt
73 pir_error_output_like pir_error_output_unlike
74 pir_output_is pir_output_isnt
75 pir_output_like pir_output_unlike
76 pir_2_pasm_is pir_2_pasm_isnt
77 pir_2_pasm_like pir_2_pasm_unlike
78 generate_languages_functions
88 is( Parrot::Test::per_test(), undef, 'per_test() no args' );
89 is( Parrot::Test::per_test( undef, 0 ), undef, 'per_test() invalid first arg' );
90 is( Parrot::Test::per_test( 0, undef ), undef, 'per_test() invalid second arg' );
91 is( Parrot::Test::per_test( undef, undef ), undef, 'per_test() two invalid args' );
93 my ( $desc, $err, $line );
96 $desc = 'pasm_output_is: success';
97 test_out("ok 1 - $desc");
98 pasm_output_is( <<'CODE', <<'OUTPUT', $desc );
106 $desc = 'pasm_output_is: failure';
107 test_out("not ok 1 - $desc");
117 pasm_output_is( <<'CODE', <<"OUTPUT", $desc );
126 $desc = 'pasm_output_isnt: success';
127 test_out("ok 1 - $desc");
128 pasm_output_isnt( <<'CODE', <<"OUTPUT", $desc );
137 # The exact error output for pasm_output_isnt() depends on the version of
138 # Test::Builder. So, in order to avoid version dependent failures, be content
139 # with checking the standard output.
141 $desc = 'pasm_output_isnt: failure';
142 test_out("not ok 1 - $desc");
153 pasm_output_isnt( <<'CODE', <<'OUTPUT', $desc );
159 test_test(title => $desc, skip_err => 1);
161 $desc = 'pasm_output_like: success';
162 test_out("ok 1 - $desc");
163 pasm_output_like( <<'CODE', <<'OUTPUT', $desc );
171 $desc = 'pasm_output_like: failure';
172 test_out("not ok 1 - $desc");
177 # doesn't match '/bar/
182 pasm_output_like( <<'CODE', <<"OUTPUT", $desc );
191 $desc = 'pir_output_is: success';
192 test_out("ok 1 - $desc");
193 pir_output_is( <<'CODE', <<'OUTPUT', $desc );
202 $desc = 'pir_output_is: failure';
203 test_out("not ok 1 - $desc");
213 pir_output_is( <<'CODE', <<"OUTPUT", $desc );
222 $desc = 'pir_output_isnt: success';
223 test_out("ok 1 - $desc");
224 pir_output_isnt( <<'CODE', <<"OUTPUT", $desc );
233 # The exact error output for pir_output_isnt() depends on the version of
234 # Test::Builder. So, in order to avoid version dependent failures, be content
235 # with checking the standard output.
236 $desc = 'pir_output_isnt: failure';
237 test_out("not ok 1 - $desc");
248 pir_output_isnt( <<'CODE', <<'OUTPUT', $desc );
255 test_test(title => $desc, skip_err => 1);
257 $desc = 'pir_output_like: success';
258 test_out("ok 1 - $desc");
259 pir_output_like( <<'CODE', <<'OUTPUT', $desc );
268 $desc = 'pir_output_like: failure';
269 test_out("not ok 1 - $desc");
274 # doesn't match '/bar/
279 pir_output_like( <<'CODE', <<"OUTPUT", $desc );
289 # incorporate changes in Test::Builder after Version 0.94
291 if ($Test::Builder::VERSION <= eval '0.94') {
292 $desc = 'pir_error_output_like: todo';
293 $line = line_num(+22);
295 if ($Test::Builder::VERSION <= eval '0.33') {
296 $location = "in $0 at line $line";
299 $location = "at $0 line $line";
301 test_out("not ok 1 - $desc # TODO foo");
303 # Failed (TODO) test '$desc'
305 # Expected error but exited cleanly
315 pir_error_output_like( <<'CODE', <<"OUTPUT", $desc, todo => 'foo' );
322 if($Test::Builder::VERSION == 0.84) {
323 test_test(title => $desc, skip_err => 1);
328 } #end of test for Test::Builder 0.94 or before
330 # Test for TEST::Builder after Version 0.94
333 $line = line_num(+14);
334 my $location = "at $0 line $line";
335 $desc = 'pir_output_like: todo';
336 test_out("not ok 1 - $desc # TODO foo");
338 # Failed (TODO) test '$desc'
342 # doesn't match '/bar/
347 pir_output_like( <<'CODE', <<"OUTPUT", $desc, todo => 'foo' );
357 ##### PIR-to-PASM output test functions #####
359 my $pir_2_pasm_code = <<'ENDOFCODE';
366 pir_2_pasm_is( <<CODE, <<'OUT', "pir_2_pasm: added return - end" );
369 # IMCC does produce b0rken PASM files
370 # see http://guest@rt.perl.org/rt3/Ticket/Display.html?id=32392
376 pir_2_pasm_isnt( <<CODE, <<'OUT', "pir_2_pasm: added return - end" );
384 pir_2_pasm_like( <<CODE, <<'OUT', "pir_2_pasm: added return - end" );
390 pir_2_pasm_unlike( <<CODE, <<'OUT', "pir_2_pasm: added return - end" );
396 my $file = q{t/perl/testlib/hello.pasm};
397 my $expected = qq{Hello World\n};
398 example_output_is( $file, $expected );
400 $expected = qq{Goodbye World\n};
401 example_output_isnt( $file, $expected );
403 $expected = qr{Hello World};
404 example_output_like( $file, $expected );
406 $file = q{t/perl/testlib/answer.pir};
407 $expected = <<EXPECTED;
412 example_output_is( $file, $expected );
414 # next is dying at _unlink_or_retain
415 $expected = <<EXPECTED;
420 example_output_isnt( $file, $expected );
422 $expected = qr/answer.*42.*Parrot!/s;
423 example_output_like( $file, $expected );
425 $file = q{t/perl/testlib/hello};
426 $expected = qq{no extension recognized for $file};
427 example_error_output_is( $file, $expected );
429 $expected = qq{some extension recognized for $file};
430 example_error_output_isnt( $file, $expected );
432 $expected = qr{no extension recognized for $file};
433 example_error_output_like( $file, $expected );
435 ##### C-output test functions #####
437 my $c_code = <<'ENDOFCODE';
442 main(int argc, char* argv[])
444 printf("Hello, World!\n");
449 $desc = 'C: is hello world';
450 test_out("ok 1 - $desc");
451 c_output_is( <<CODE, <<'OUTPUT', $desc );
458 $desc = 'C: isnt hello world';
459 test_out("ok 1 - $desc");
460 c_output_isnt( <<CODE, <<'OUTPUT', $desc );
467 $desc = 'C: like hello world';
468 test_out("ok 1 - $desc");
469 c_output_like( <<CODE, <<'OUTPUT', $desc );
476 $desc = 'C: unlike hello world';
477 test_out("ok 1 - $desc");
478 c_output_unlike( <<CODE, <<'OUTPUT', $desc );
485 ##### Tests for Parrot::Test internal subroutines #####
487 # _handle_test_options()
489 ( $out, $err, $chdir ) = Parrot::Test::_handle_test_options( {
490 STDOUT => '/tmp/captureSTDOUT',
491 STDERR => '/tmp/captureSTDERR',
494 is($out, '/tmp/captureSTDOUT', "Got expected value for STDOUT");
495 is($err, '/tmp/captureSTDERR', "Got expected value for STDERR");
496 is($chdir, '/tmp', "Got expected value for working directory");
498 ( $out, $err, $chdir ) = Parrot::Test::_handle_test_options( {
499 STDOUT => '/tmp/captureSTDOUT',
503 is($out, '/tmp/captureSTDOUT', "Got expected value for STDOUT");
504 is($err, '', "Got expected value for STDERR");
505 is($chdir, '/tmp', "Got expected value for working directory");
507 ( $out, $err, $chdir ) = Parrot::Test::_handle_test_options( {
512 is($out, '', "Got expected value for STDOUT");
513 is($err, '', "Got expected value for STDERR");
514 is($chdir, '', "Got expected value for working directory");
517 ( $out, $err, $chdir ) = Parrot::Test::_handle_test_options( {
523 like($@, qr/I don't know how to redirect 'STDJ' yet!/,
524 "Got expected error message for bad option");
526 my $dn = File::Spec->devnull();
527 ( $out, $err, $chdir ) = Parrot::Test::_handle_test_options( {
529 STDERR => ($^O eq 'MSWin32')? 'nul' : '/dev/null',
532 is($out, '', "Got expected value for STDOUT");
533 is($err, $dn, "Got expected value for STDERR using null device");
534 is($chdir, '', "Got expected value for working directory");
536 ( $out, $err, $chdir ) = Parrot::Test::_handle_test_options( {
537 STDOUT => '/tmp/foobar',
538 STDERR => '/tmp/foobar',
541 is($out, '/tmp/foobar', "Got expected value for STDOUT");
542 is($err, '&STDOUT', "Got expected value for STDERR when same as STDOUT");
543 is($chdir, '', "Got expected value for working directory");
546 my $oldpath = $ENV{PATH};
547 my $oldldrunpath = $ENV{LD_RUN_PATH};
548 local $PConfig{build_dir} = 'foobar';
549 my $blib_path = File::Spec->catfile( $PConfig{build_dir}, 'blib', 'lib' );
551 local $^O = 'cygwin';
552 Parrot::Test::_handle_blib_path();
553 is( $ENV{PATH}, $blib_path . ':' . $oldpath,
554 "\$ENV{PATH} reset as expected for $^O");
555 $ENV{PATH} = $oldpath;
558 local $^O = 'MSWin32';
559 Parrot::Test::_handle_blib_path();
560 is( $ENV{PATH}, $blib_path . ';' . $oldpath,
561 "\$ENV{PATH} reset as expected for $^O");
562 $ENV{PATH} = $oldpath;
565 local $^O = 'not_cygwin_not_MSWin32';
566 Parrot::Test::_handle_blib_path();
567 is( $ENV{LD_RUN_PATH}, $blib_path,
568 "\$ENV{LD_RUN_PATH} reset as expected for $^O");
569 $ENV{LD_RUN_PATH} = $oldldrunpath;
574 $command_orig = 'ls';
575 is_deeply( Parrot::Test::_handle_command($command_orig), [ qw( ls ) ],
576 "Scalar command transformed into array ref as expected");
577 $command_orig = [ qw( ls -l ) ];
578 is( Parrot::Test::_handle_command($command_orig), $command_orig,
579 "Array ref holding multiple commands unchanged as expected");
582 my $oldvalgrind = defined $ENV{VALGRIND} ? $ENV{VALGRIND} : '';
583 $command_orig = 'ls';
585 local $ENV{VALGRIND} = $foo;
586 my $ret = Parrot::Test::_handle_command($command_orig);
588 is( $ret->[0], "$foo $command_orig",
589 "Got expected value in Valgrind environment");
591 $ENV{VALGRIND} = $oldvalgrind;
596 my $exit_message = Parrot::Test::_prepare_exit_message();
597 is( $exit_message, -1, "Got expected exit message" );
602 my $exit_message = Parrot::Test::_prepare_exit_message();
603 is( $exit_message, 0, "Got expected exit message" );
608 my $exit_message = Parrot::Test::_prepare_exit_message();
609 is( $exit_message, q{[SIGNAL 1]}, "Got expected exit message" );
614 my $exit_message = Parrot::Test::_prepare_exit_message();
615 is( $exit_message, q{[SIGNAL 255]}, "Got expected exit message" );
620 my $exit_message = Parrot::Test::_prepare_exit_message();
621 is( $exit_message, 1, "Got expected exit message" );
626 my $exit_message = Parrot::Test::_prepare_exit_message();
627 is( $exit_message, 2, "Got expected exit message" );
631 my $q = $PConfig{PQ};
632 my $text = q{Hello, world};
633 my $cmd = "$^X -e ${q}print qq{$text\n};${q}";
635 my ($stdout, $stderr);
638 $exit_message = run_command(
645 like($stdout, qr/$text/, "Captured STDOUT");
646 is($exit_message, 0, "Got 0 as exit message");
654 skip 'feature not DWIMming even though test passes',
657 test_out("ok 1 - $desc");
658 pasm_output_is( <<'CODE', <<'OUTPUT', $desc );
667 my $outfile = File::Spec->catfile( qw| t perl Parrot_Test_1.out | );
670 local $ENV{POSTMORTEM} = 1;
671 $desc = 'pir_output_is: success';
672 test_out("ok 1 - $desc");
673 pir_output_is( <<'CODE', <<'OUTPUT', $desc );
682 "file created during test preserved due to \$ENV{POSTMORTEM}");
685 "file created during test has been deleted");
690 local $ENV{POSTMORTEM} = 0;
691 $desc = 'pir_output_is: success';
692 test_out("ok 1 - $desc");
693 pir_output_is( <<'CODE', <<'OUTPUT', $desc );
702 "file created during test was not retained");
708 unless ( $ENV{POSTMORTEM} ) {
709 my $tdir = q{t/perl};
710 opendir my $DIRH, $tdir or croak "Unable to open $tdir for reading: $!";
712 grep { m/Parrot_Test_\d+\.(?:pir|pasm|out|c|o|build)$/ }
714 closedir $DIRH or croak "Unable to close $tdir after reading: $!";
715 for my $f (@need_cleanup) {
716 unlink qq{$tdir/$f} or croak "Unable to remove $f: $!";
722 # cperl-indent-level: 4
725 # vim: expandtab shiftwidth=4: