tagged release 0.6.4
[parrot.git] / lib / Parrot / Test / Harness.pm
blobfc3f66db2764fff3000b1ab5a82798d6e881f2d3
1 # Copyright (C) 2006-2008, The Perl Foundation.
2 # $Id$
4 =head1 NAME
6 Parrot::Test::Harness - a test harness for languages built on Parrot
8 =head1 SYNOPSIS
10 Tell the harness which language, and optionally compiler or other executable,
11 you want to use in a file called F<t/harness>:
13 use Parrot::Test::Harness language => 'punie';
15 # or
17 use Parrot::Test::Harness language => 'perl6', compiler => 'perl6.pbc';
19 # or
21 use Parrot::Test::Harness
22 language => 'eclectus',
23 exec => [ 'petite', '--script' ],
24 arguments => [ '--files' ],
25 files => [ 't/*.pl' ];
27 That's it. Seriously.
29 =head1 DESCRIPTION
31 This module provides a basic test harness for Parrot-hosted languages. Right
32 now it parameterizes the three parameters that at least four language
33 implementations need.
35 If you really want, you can pass a third option to the C<use> line.
36 C<arguments> should be an array reference containing additional arguments (as
37 you might find on the command line).
39 If you don't pass a C<compiler> or C<exec> argument pair, the harness will run the tests
40 with C<perl>. If you I<do> pass one of these pairs, the harness can use another executable.
41 For C<exec> a reference to a an array of string is expected.
42 For C<compiler> the harness will run the tests with
43 C<parrot>, calling the C<compiler> file as the first argument.
45 This means that you can write your tests in your language itself and run them
46 through your compiler itself. If you can load PIR libraries from your
47 language, you can even use the existing PIR testing tools.
49 =head1 AUTHOR
51 Written by chromatic with most of the intelligence stolen from the Punie
52 harness and most of that probably stolen from Test::Harness
54 Please send patches and bug reports via Parrot's RT queue or to the mailing
55 list.
57 =cut
59 package Parrot::Test::Harness;
61 use strict;
62 use warnings;
64 use Carp;
65 use File::Spec;
66 use Test::Harness;
67 use List::Util;
69 sub set_flags {
70 my %options = @_;
72 $ENV{HARNESS_VERBOSE} = 1;
73 if ( $options{exec} ) {
74 $ENV{HARNESS_PERL} ||= join q{ }, @{$options{exec}};
76 elsif ( $options{compiler} ) {
77 $ENV{HARNESS_PERL} ||= join q{}, "../../parrot ./$options{compiler}";
80 return;
83 # return a list of test files
84 sub get_files {
85 my %options = @_;
87 =pod
89 The option '--files' is used for supporting unified testing of language implementations.
90 It is used by F<languages/t/harness> for collecting a list testfiles from
91 many language implementations.
93 When that option is passed, a list of pathes to test files is printed.
94 Currently these test files need to Perl 5 scripts.
95 The file pathes are relative to a language implementation dir.
97 When there is no '--files' option, then things are saner.
98 Nothing is printed. An array of file pathes is returned to the caller.
100 =cut
102 if ( grep { m/^--files$/ } @{ $options{arguments} } ) {
104 # --files indicates that 'languages/t/harness' wants a list of test files
105 my @files;
107 # file patterns are either passed from a <language>/t/harness,
108 # or the default is used
109 my @file_patterns =
110 ( $options{files} && ref $options{files} eq 'ARRAY' ) ?
111 @{ $options{files} }
113 ( 't/*.t', 't/*/*.t' );
114 if ( List::Util::first { $_ eq '--master' } @{ $options{arguments} } ) {
115 # if --master is passed, add the language dir as a prefix
116 @files = map { glob( File::Spec->catfile( $options{language}, $_ ) )
118 @file_patterns;
120 else {
121 @files = map { glob( $_ )
123 @file_patterns;
126 print map { $_ . "\n" } @files;
128 exit;
130 elsif ( @{ $options{arguments} } ) {
132 # Someone specified tests for me to run.
133 my @files;
134 foreach my $arg ( @{ $options{arguments} } ) {
135 -f $arg && push @files, glob $arg;
136 -d $arg && push @files, glob( File::Spec->catfile( $arg, '*.t' ) );
139 return @files;
141 else {
142 # file patterns are either passed from a <language>/t/harness,
143 # or the default is used
144 my @file_patterns =
145 ( $options{files} && ref $options{files} eq 'ARRAY' ) ?
146 @{ $options{files} }
148 ( 't/*.t', 't/*/*.t' );
149 return map { glob( $_ )
151 @file_patterns;
155 sub import {
156 my ( $class, %options ) = @_;
158 croak "Need a language\n" unless $options{language};
160 $options{arguments} ||= \@ARGV;
162 exit unless my @files = get_files(%options);
164 if (eval { require TAP::Harness; 1 }) {
165 my %options =
166 $options{exec} ? ( exec => $options{exec} )
167 : $options{compiler} ? ( exec => [ '../../parrot', './' . $options{compiler} ] )
168 : ();
169 TAP::Harness->new( \%options )->runtests( @files );
171 return;
174 set_flags(%options);
176 local $Test::Harness::Switches = '';
178 no warnings 'redefine';
179 local *Test::Harness::Straps::_INC2PERL5LIB = ## no critic Variables::ProhibitConditionalDeclarations
180 sub { @INC }
181 if $options{compiler};
183 runtests(@files);
188 # Local Variables:
189 # mode: cperl
190 # cperl-indent-level: 4
191 # fill-column: 100
192 # End:
193 # vim: expandtab shiftwidth=4: