Please review the patch attached, which consists of 5 new test files: t/configure/109-inter_lex.01.t ... thru ... t/configure/109-inter_lex.05.t
... as well as a refactored config/inter/lex.pm. The refactorings had as their objectives (a) eliminating untestable parts of conditions; and (b) providing a way to rig up tests of code depending on settings of environmental values. Feedback welcome on OSes other than Darwin and Linux. Thank you very much. kid51
Index: MANIFEST =================================================================== --- MANIFEST (revision 21118) +++ MANIFEST (working copy) @@ -1,7 +1,7 @@ # ex: set ro: # $Id$ # -# generated by tools/dev/mk_manifest_and_skip.pl Thu Sep 6 19:17:40 2007 UT +# generated by tools/dev/mk_manifest_and_skip.pl Fri Sep 7 02:52:21 2007 UT # # See tools/dev/install_files.pl for documentation on the # format of this file. @@ -2928,6 +2928,11 @@ t/configure/106-init_headers.t [] t/configure/107-inter_progs.01.t [] t/configure/107-inter_progs.02.t [] +t/configure/109-inter_lex.01.t [] +t/configure/109-inter_lex.02.t [] +t/configure/109-inter_lex.03.t [] +t/configure/109-inter_lex.04.t [] +t/configure/109-inter_lex.05.t [] t/configure/testlib/Make_VERSION_File.pm [] t/configure/testlib/Tie/Filehandle/Preempt/Stdin.pm [] t/configure/testlib/init/alpha.pm [] Index: t/configure/109-inter_lex.01.t =================================================================== --- t/configure/109-inter_lex.01.t (revision 0) +++ t/configure/109-inter_lex.01.t (revision 0) @@ -0,0 +1,80 @@ +#! perl +# Copyright (C) 2007, The Perl Foundation. +# $Id$ +# 109-inter_lex.01.t + +use strict; +use warnings; +use Test::More tests => 12; +use Carp; +use lib qw( lib t/configure/testlib ); +use_ok('config::init::defaults'); +use_ok('config::inter::lex'); +use Parrot::Configure; +use Parrot::Configure::Options qw( process_options ); +use Parrot::IO::Capture::Mini; +use Parrot::Configure::Test qw( test_step_thru_runstep); + +my $args = process_options( { + argv => [ q{--ask} ], + mode => q{configure}, +} ); + +my $conf = Parrot::Configure->new(); + +test_step_thru_runstep($conf, q{init::defaults}, $args); + +my ($task, $step_name, @step_params, $step, $ret); +my $pkg = q{inter::lex}; + +$conf->add_steps($pkg); +$conf->options->set(%{$args}); +$task = $conf->steps->[1]; +$step_name = $task->step; [EMAIL PROTECTED] = @{ $task->params }; + +$step = $step_name->new(); +ok(defined $step, "$step_name constructor returned defined value"); +isa_ok($step, $step_name); +ok($step->description(), "$step_name has description"); +$ret = $step->runstep($conf); +ok(defined $ret, "$step_name runstep() returned defined value"); +is($step->result(), q{skipped}, + "Step was skipped as expected; no '--maintainer' option"); + +pass("Completed all tests in $0"); + +################### DOCUMENTATION ################### + +=head1 NAME + +109-inter_lex.01.t - test config::inter::lex + +=head1 SYNOPSIS + + % prove t/configure/109-inter_lex.01.t + +=head1 DESCRIPTION + +The files in this directory test functionality used by F<Configure.pl>. + +The tests in this file test subroutines exported by config::inter::lex. In +this case, only the C<--ask> option is provided. Because the C<--maintainer> +option is not provided, the step is skipped and no prompt is ever reached. + +=head1 AUTHOR + +James E Keenan + +=head1 SEE ALSO + +config::inter::lex, F<Configure.pl>. + +=cut + +# Local Variables: +# mode: cperl +# cperl-indent-level: 4 +# fill-column: 100 +# End: +# vim: expandtab shiftwidth=4: Property changes on: t/configure/109-inter_lex.01.t ___________________________________________________________________ Name: svn:mime-type + text/plain Name: svn:keywords + Author Date Id Revision Name: svn:eol-style + native Index: t/configure/109-inter_lex.02.t =================================================================== --- t/configure/109-inter_lex.02.t (revision 0) +++ t/configure/109-inter_lex.02.t (revision 0) @@ -0,0 +1,84 @@ +#! perl +# Copyright (C) 2007, The Perl Foundation. +# $Id$ +# 109-inter_lex.02.t + +use strict; +use warnings; +use Test::More tests => 12; +use Carp; +use lib qw( lib t/configure/testlib ); +use_ok('config::init::defaults'); +use_ok('config::inter::lex'); +use Parrot::Configure; +use Parrot::Configure::Options qw( process_options ); +use Parrot::Configure::Test qw( test_step_thru_runstep); + +$ENV{LEX} = 'foobar'; + +my $args = process_options( { + argv => [ q{--ask}, q{--maintainer} ], + mode => q{configure}, +} ); + +my $conf = Parrot::Configure->new(); + +test_step_thru_runstep($conf, q{init::defaults}, $args); + +my ($task, $step_name, @step_params, $step, $ret); +my $pkg = q{inter::lex}; + +$conf->add_steps($pkg); +$conf->options->set(%{$args}); + +$task = $conf->steps->[1]; +$step_name = $task->step; [EMAIL PROTECTED] = @{ $task->params }; + +$step = $step_name->new(); +ok(defined $step, "$step_name constructor returned defined value"); +isa_ok($step, $step_name); +ok($step->description(), "$step_name has description"); +$ret = $step->runstep($conf); +ok(defined $ret, "$step_name runstep() returned defined value"); +my $result_expected = q{user defined}; +is($step->result(), $result_expected, + "Result was $result_expected because environmental variable was set"); + +pass("Completed all tests in $0"); + +################### DOCUMENTATION ################### + +=head1 NAME + +109-inter_lex.02.t - test config::inter::lex + +=head1 SYNOPSIS + + % prove t/configure/109-inter_lex.02.t + +=head1 DESCRIPTION + +The files in this directory test functionality used by F<Configure.pl>. + +The tests in this file test subroutines exported by config::inter::lex. In +this case, the C<--ask> and C<--maintainer> options are provided but the +F<lex>-equivalent program is provided by the user via an environmental +variable. As a result, no prompt is ever reached. + +=head1 AUTHOR + +James E Keenan + +=head1 SEE ALSO + +config::inter::lex, F<Configure.pl>. + +=cut + +# Local Variables: +# mode: cperl +# cperl-indent-level: 4 +# fill-column: 100 +# End: +# vim: expandtab shiftwidth=4: Property changes on: t/configure/109-inter_lex.02.t ___________________________________________________________________ Name: svn:mime-type + text/plain Name: svn:keywords + Author Date Id Revision Name: svn:eol-style + native Index: t/configure/109-inter_lex.03.t =================================================================== --- t/configure/109-inter_lex.03.t (revision 0) +++ t/configure/109-inter_lex.03.t (revision 0) @@ -0,0 +1,84 @@ +#! perl +# Copyright (C) 2007, The Perl Foundation. +# $Id$ +# 109-inter_lex.03.t + +use strict; +use warnings; +use Test::More tests => 12; +use Carp; +use lib qw( lib t/configure/testlib ); +use_ok('config::init::defaults'); +$ENV{TEST_LEX} = 'foobar'; +use_ok('config::inter::lex'); +use Parrot::Configure; +use Parrot::Configure::Options qw( process_options ); +use Parrot::Configure::Test qw( test_step_thru_runstep); + +my $args = process_options( { + argv => [ q{--ask}, q{--maintainer} ], + mode => q{configure}, +} ); + +my $conf = Parrot::Configure->new(); + +test_step_thru_runstep($conf, q{init::defaults}, $args); + +my ($task, $step_name, @step_params, $step, $ret); +my $pkg = q{inter::lex}; + +$conf->add_steps($pkg); +$conf->options->set(%{$args}); + +$task = $conf->steps->[1]; +$step_name = $task->step; [EMAIL PROTECTED] = @{ $task->params }; + +$step = $step_name->new(); +ok(defined $step, "$step_name constructor returned defined value"); +isa_ok($step, $step_name); +ok($step->description(), "$step_name has description"); +$ret = $step->runstep($conf); +is($ret, undef, "$step_name runstep() returned undefined value"); +my $result_expected = q{no lex program was found}; +is($step->result(), $result_expected, + "Result was $result_expected"); + +pass("Completed all tests in $0"); + +################### DOCUMENTATION ################### + +=head1 NAME + +109-inter_lex.03.t - test config::inter::lex + +=head1 SYNOPSIS + + % prove t/configure/109-inter_lex.03.t + +=head1 DESCRIPTION + +The files in this directory test functionality used by F<Configure.pl>. + +The tests in this file test subroutines exported by config::inter::lex. In +this case, the C<--ask> and C<--maintainer> options are provided but an +environmental variable was provided in order to trick the package into not +finding a real F<lex>-equivalent program. As a result, no prompt is ever +reached. + +=head1 AUTHOR + +James E Keenan + +=head1 SEE ALSO + +config::inter::lex, F<Configure.pl>. + +=cut + +# Local Variables: +# mode: cperl +# cperl-indent-level: 4 +# fill-column: 100 +# End: +# vim: expandtab shiftwidth=4: Property changes on: t/configure/109-inter_lex.03.t ___________________________________________________________________ Name: svn:mime-type + text/plain Name: svn:keywords + Author Date Id Revision Name: svn:eol-style + native Index: t/configure/109-inter_lex.04.t =================================================================== --- t/configure/109-inter_lex.04.t (revision 0) +++ t/configure/109-inter_lex.04.t (revision 0) @@ -0,0 +1,93 @@ +#! perl +# Copyright (C) 2007, The Perl Foundation. +# $Id$ +# 109-inter_lex.04.t + +use strict; +use warnings; +use Test::More tests => 14; +use Carp; +use lib qw( lib t/configure/testlib ); +use_ok('config::init::defaults'); +use_ok('config::inter::lex'); +use Parrot::Configure; +use Parrot::Configure::Options qw( process_options ); +use Parrot::Configure::Test qw( test_step_thru_runstep); +use Tie::Filehandle::Preempt::Stdin; + +my $args = process_options( { + argv => [ q{--ask}, q{--maintainer}, q{--lex=flex} ], + mode => q{configure}, +} ); + +my $conf = Parrot::Configure->new(); + +test_step_thru_runstep($conf, q{init::defaults}, $args); + +my (@prompts, $object, @entered); [EMAIL PROTECTED] = map { q{foo_} . $_ } + qw| alpha |; [EMAIL PROTECTED] = ( q{lex} ); +$object = tie *STDIN, 'Tie::Filehandle::Preempt::Stdin', @prompts; +can_ok('Tie::Filehandle::Preempt::Stdin', ('READLINE')); +isa_ok($object, 'Tie::Filehandle::Preempt::Stdin'); + +my ($task, $step_name, @step_params, $step, $ret); +my $pkg = q{inter::lex}; + +$conf->add_steps($pkg); +$conf->options->set(%{$args}); + +$task = $conf->steps->[1]; +$step_name = $task->step; [EMAIL PROTECTED] = @{ $task->params }; + +$step = $step_name->new(); +ok(defined $step, "$step_name constructor returned defined value"); +isa_ok($step, $step_name); +ok($step->description(), "$step_name has description"); +$ret = $step->runstep($conf); +ok(defined $ret, "$step_name runstep() returned defined value"); +my $result_expected = q{user defined}; +is($step->result(), $result_expected, + "Result was $result_expected"); + +$object = undef; +untie *STDIN; + +pass("Completed all tests in $0"); + +################### DOCUMENTATION ################### + +=head1 NAME + +109-inter_lex.04.t - test config::inter::lex + +=head1 SYNOPSIS + + % prove t/configure/109-inter_lex.04.t + +=head1 DESCRIPTION + +The files in this directory test functionality used by F<Configure.pl>. + +The tests in this file test subroutines exported by config::inter::lex. In +this test the C<--ask>, C<--maintainer> and C<--lex=flex> options are +provided. + +=head1 AUTHOR + +James E Keenan + +=head1 SEE ALSO + +config::inter::lex, F<Configure.pl>. + +=cut + +# Local Variables: +# mode: cperl +# cperl-indent-level: 4 +# fill-column: 100 +# End: +# vim: expandtab shiftwidth=4: Property changes on: t/configure/109-inter_lex.04.t ___________________________________________________________________ Name: svn:mime-type + text/plain Name: svn:keywords + Author Date Id Revision Name: svn:eol-style + native Index: t/configure/109-inter_lex.05.t =================================================================== --- t/configure/109-inter_lex.05.t (revision 0) +++ t/configure/109-inter_lex.05.t (revision 0) @@ -0,0 +1,109 @@ +#! perl +# Copyright (C) 2007, The Perl Foundation. +# $Id$ +# 109-inter_lex.05.t + +use strict; +use warnings; +use Data::Dumper; +use Test::More tests => 14; +use Carp; +use lib qw( lib t/configure/testlib ); +use_ok('config::init::defaults'); +use_ok('config::inter::lex'); +use Parrot::Configure; +use Parrot::Configure::Options qw( process_options ); +use Parrot::IO::Capture::Mini; +use Parrot::Configure::Test qw( test_step_thru_runstep); +use Tie::Filehandle::Preempt::Stdin; + +my $args = process_options( { + argv => [ q{--ask}, q{--maintainer} ], + mode => q{configure}, +} ); + +my $conf = Parrot::Configure->new(); + +test_step_thru_runstep($conf, q{init::defaults}, $args); + +my (@prompts, $object, @entered); [EMAIL PROTECTED] = q{flex}; +$object = tie *STDIN, 'Tie::Filehandle::Preempt::Stdin', @prompts; +can_ok('Tie::Filehandle::Preempt::Stdin', ('READLINE')); +isa_ok($object, 'Tie::Filehandle::Preempt::Stdin'); + +my ($task, $step_name, @step_params, $step, $ret); +my $pkg = q{inter::lex}; + +$conf->add_steps($pkg); +$conf->options->set(%{$args}); + +$task = $conf->steps->[1]; +$step_name = $task->step; [EMAIL PROTECTED] = @{ $task->params }; + +$step = $step_name->new(); +ok(defined $step, "$step_name constructor returned defined value"); +isa_ok($step, $step_name); +ok($step->description(), "$step_name has description"); + +{ + my $tie_out = tie *STDOUT, "Parrot::IO::Capture::Mini" + or croak "Unable to tie"; + $ret = $step->runstep($conf); + my @more_lines = $tie_out->READLINE; + my $possible_results = qr/^( + no\slex\sprogram\swas\sfound + | lex\sprogram\sdoes\snot\sexist\sor\sdoes\snot\sunderstand\s--version + | could\snot\sunderstand\sflex\sversion\srequirement + | found\sflex\sversion.*?but\sat\sleast.*?is\srequired + | flex + )/x; + my @dump_msg = ( Dumper($step->result()) =~ /'(.*?)'/ ); + like($step->result(), $possible_results, + "Response to prompt led to acceptable result: " . $dump_msg[0]); + if ($dump_msg[0] eq q{no lex program was found}) { + ok(! @more_lines, "No lex program => no prompts"); + } else { + ok(@more_lines, "prompts were captured"); + } +} + + +$object = undef; +untie *STDIN; + +pass("Completed all tests in $0"); + +################### DOCUMENTATION ################### + +=head1 NAME + +109-inter_lex.05.t - test config::inter::lex + +=head1 SYNOPSIS + + % prove t/configure/109-inter_lex.05.t + +=head1 DESCRIPTION + +The files in this directory test functionality used by F<Configure.pl>. + +The tests in this file test subroutines exported by config::inter::lex. + +=head1 AUTHOR + +James E Keenan + +=head1 SEE ALSO + +config::inter::lex, F<Configure.pl>. + +=cut + +# Local Variables: +# mode: cperl +# cperl-indent-level: 4 +# fill-column: 100 +# End: +# vim: expandtab shiftwidth=4: Property changes on: t/configure/109-inter_lex.05.t ___________________________________________________________________ Name: svn:mime-type + text/plain Name: svn:keywords + Author Date Id Revision Name: svn:eol-style + native Index: config/inter/lex.pm =================================================================== --- config/inter/lex.pm (revision 21118) +++ config/inter/lex.pm (working copy) @@ -28,6 +28,10 @@ $prompt = "Do you have a lexical analyzer generator like flex or lex?"; @args = qw( lex ask maintainer ); +my @lex_defaults = defined($ENV{TEST_LEX}) + ? $ENV{TEST_LEX} + : qw( flex lex ); + my $default_required = '2.5.33'; sub runstep { @@ -44,12 +48,12 @@ return $self; } - my $prog; - # precedence of sources for the program: # default -> probe -> environment -> option -> ask - $prog ||= $conf->options->get($util); - $prog ||= $ENV{ uc($util) }; + my $prog = $conf->options->get($util); + unless ($prog) { + $prog = $ENV{ uc($util) }; + } # never override the user. If a non-existent program is specified then # the user is responsible for the consequences. @@ -57,77 +61,71 @@ $conf->data->set( $util => $prog ); $self->set_result('user defined'); return $self; - } - - $prog = check_progs( [ 'flex', 'lex' ], $verbose ); - - unless ($prog) { - $self->set_result('no lex program was found'); - return; - } - - # RT#43170 should --ask be handled like the other user defines or - # checked for version requirements? - if ( $conf->options->get('ask') ) { - $prog = prompt( $prompt, $prog ? $prog : $conf->data->get($util) ); - } - - my ( $stdout, $stderr, $ret ) = capture_output( $prog, '--version' ); - - # don't override the user even if the program they provided appears to be - # broken - if ( $ret == -1 and !$conf->options->get('ask') ) { - - # fall back to default - $self->set_result('lex program does not exist or does not understand --version'); - return; - } - - # if '--version' returns a string assume that this is flex. - # flex calls it self by $0 so it will claim to be lex if invoked as `lex` - if ( $stdout =~ /f?lex .*? (\d+) \. (\d+) \. (\d+)/x ) { - my ( $prog_major, $prog_minor, $prog_patch ) = ( $1, $2, $3 ); - my $prog_version = "$1.$2.$3"; - - # is there a version requirement? - my $req = $conf->options->get('flex_required'); - unless ( defined $req ) { - $req = $default_required; - } - if ($req) { - my ( $rmajor, $rminor, $rpatch ) = ( $req =~ / ^ (\d+) \. (\d+) \. (\d+) $ /x ); - unless ( defined $rmajor ) { - $self->set_result("could not understand flex version requirement"); - return; + } else { + $prog = check_progs( [ @lex_defaults ], $verbose ); + if (! $prog) { + $self->set_result('no lex program was found'); + return; + } else { + # RT#43170 should --ask be handled like the other user defines or + # checked for version requirements? + if ( $conf->options->get('ask') ) { + $prog = prompt( + $prompt, $prog ? $prog : $conf->data->get($util) + ); } - - if ( - $prog_major < $rmajor - - or ( $prog_major == $rmajor - and $prog_minor < $rminor ) - - or ( $prog_major == $rmajor - and $prog_minor == $rminor - and $prog_patch < $rpatch ) - ) - { - $self->set_result( "found flex version $prog_version" - . " but at least $rmajor.$rminor.$rpatch is required" ); + my ( $stdout, $stderr, $ret ) = + capture_output( $prog, '--version' ); + # don't override the user even if the program they provided + # appears to be broken + if ( $ret == -1 and !$conf->options->get('ask') ) { + # fall back to default + $self->set_result('lex program does not exist or does not understand --version'); return; + } elsif ( $stdout =~ /f?lex .*? (\d+) \. (\d+) \. (\d+)/x ) { + # if '--version' returns a string assume that this is flex. + # flex calls it self by $0 so it will claim to be lex + # if invoked as `lex` + my ( $prog_major, $prog_minor, $prog_patch ) = ( $1, $2, $3 ); + my $prog_version = "$1.$2.$3"; + + # is there a version requirement? + my $req = $conf->options->get('flex_required'); + unless ( defined $req ) { + $req = $default_required; + } + if ($req) { + my ( $rmajor, $rminor, $rpatch ) = + ( $req =~ / ^ (\d+) \. (\d+) \. (\d+) $ /x ); + if (! defined $rmajor ) { + $self->set_result( + "could not understand flex version requirement"); + return; + } elsif ( + $prog_major < $rmajor + or ( $prog_major == $rmajor + and $prog_minor < $rminor ) + or ( $prog_major == $rmajor + and $prog_minor == $rminor + and $prog_patch < $rpatch ) + ) { + $self->set_result( "found flex version $prog_version" + . " but at least $rmajor.$rminor.$rpatch is required" ); + return; + } else { + 1; # lack an explicit 'else' here + } + } + $conf->data->set( flex_version => $prog_version ); + $self->set_result("flex $prog_version"); + $conf->data->set( $util => $prog ); + return $self; + } else { + $self->set_result('lex program does not exist or does not understand --version'); + return; } } - - $conf->data->set( flex_version => $prog_version ); - $self->set_result("flex $prog_version"); - $conf->data->set( $util => $prog ); } - else { - $self->set_result('lex program does not exist or does not understand --version'); - return; - } - - return $self; } 1;