%PDF- %PDF-
Direktori : /root/.cpanm/latest-build/CPAN-2.27/t/ |
Current File : //root/.cpanm/latest-build/CPAN-2.27/t/31sessions.t |
#!/usr/bin/perl # use 5.010; use strict; use warnings; =head1 NAME =head1 SYNOPSIS =head1 OPTIONS =over 8 =cut our @opt; BEGIN { @opt = <<'=back' =~ /B<--(\S+)>/g; =item B<--debug!> Noise =item B<--help|h!> This help =item B<--pause!> After every session make a pause, waiting for an ENTER keypress. =item B<--session=s@> execute only the session with this name. =item B<--verbose|v!> display the actual output of all executed commands =back } =head1 DESCRIPTION =cut use FindBin; use lib "$FindBin::Bin/../lib"; BEGIN { push @INC, qw( ); } use Dumpvalue; use File::Basename qw(dirname); use File::Path qw(mkpath); use File::Spec; use File::Temp; use Getopt::Long; use Pod::Usage; our %Opt; my %limit_to_sessions; my $cnt; $|=1; BEGIN { eval { # may fail, e.g. on 5.6.2 which has no Hash::Util require Hash::Util; Hash::Util::lock_keys(%Opt, map { /([^=!\|]+)/ } @opt); }; $cnt = 0; unshift @INC, './lib', './t'; GetOptions(\%Opt, @opt, ) or pod2usage(1); if ($Opt{help}) { pod2usage(0); exit; } if ($Opt{session}) { %limit_to_sessions = map {($_=>1)} @{$Opt{session}}; } if ($Opt{debug}) { require YAML::Syck; } require local_utils; local_utils::cleanup_dot_cpan(); local_utils::prepare_dot_cpan(); local_utils::read_myconfig(); require CPAN::MyConfig; require CPAN; CPAN::HandleConfig->load; $CPAN::Config->{load_module_verbosity} = q[none]; my $yaml_module = CPAN::_yaml_module(); my $exit_message; # local $CPAN::Be_Silent = 1; # not the official interface!!! if ($CPAN::META->has_inst($yaml_module)) { # print "# yaml_module[$yaml_module] loadable\n"; } else { $exit_message = "Yaml module [$yaml_module] not installed"; } if ($CPAN::META->has_inst("Module::Build")) { # print "# Module::Build loadable\n"; } else { $exit_message = "Module::Build not installed"; } if ($CPAN::META->has_inst("File::Temp")) { # print "# File::Temp loadable\n"; } else { $exit_message = "File::Temp not available"; } TABU: for my $tabu (qw( CPAN::Test::Dummy::Perl5::Make CPAN::Test::Dummy::Perl5::Make::ConfReq CPAN::Test::Dummy::Perl5::Build::Fails CPAN::Test::Dummy::Perl5::Make::CircDepeOne CPAN::Test::Dummy::Perl5::Make::CircDepeTwo CPAN::Test::Dummy::Perl5::Make::CircDepeThree CPAN::Test::Dummy::Perl5::Make::Features CPAN::Test::Dummy::Perl5::Make::UnsatPrereq )) { if ($CPAN::META->has_inst($tabu)) { $exit_message = "Found module '$tabu' installed. Cannot run this test."; last TABU; } } unless ($exit_message) { if ($YAML::VERSION && $YAML::VERSION < 0.60) { $exit_message = "YAML v$YAML::VERSION too old for this test"; } } unless ($exit_message) { my @pairs = ( [unzip => "Archive::Zip"], [tar => "Archive::Tar"], [gzip => "Compress::Zlib"], ); my $p; my(@path) = split /$Config::Config{path_sep}/, $ENV{PATH}; require CPAN::FirstTime; my $pair; for $pair (@pairs) { my($prg,$module) = @$pair; next if $CPAN::META->has_inst($module); next if CPAN::FirstTime::find_exe($prg,\@path); $exit_message = "Module '$module' not installed and fallback program '$prg' not found in path[@path]."; last; } } if ($exit_message) { $|=1; print "1..0 # SKIP $exit_message\n"; eval "require POSIX; 1" and POSIX::_exit(0); warn "Error while trying to load POSIX: $@"; exit(0); } } use File::Copy qw(cp); use File::Spec; use Test::More; =pod It was our intent to shape the force pragma as follows: Do we want to repeat testing? command session restored_state Distro OK no no no FAIL no yes yes Module/Bundle OK/FAIL pass everything through to underlying distros =cut BEGIN { for my $x ( "_f", "read_myconfig", "mydiag", "run_shell_cmd_lit", ) { no strict "refs"; *$x = \&{"local_utils\::$x"}; } } END { unlink "test-$$.out"; local_utils::cleanup_dot_cpan(); } our(@SESSIONS, $default_system, $prompt_re); BEGIN { my $cwd = CPAN::anycwd(); # 2>&1 is no solution. I intertwingled them, I missed a few "ok" $default_system = join(" ", map { "\"$_\"" } run_shell_cmd_lit($cwd,$$))." > test-$$.out"; open FH, (">" . _f"t/dot-cpan-$$/prefs/TestDistroPrefsFile.yml") or die "Could not open: $!"; print FH <<EOF; --- match: distribution: "ANDK/CPAN-Test-Dummy-Perl5-Make-Features-" features: - "rice" EOF close FH or die "Could not close 't/dot-cpan-$$/prefs/TestDistroPrefsFile.yml': $!"; @SESSIONS = ( { name => "illegal-regexp", perl_mm_use_default => 0, pairs => [ "o conf /*list/" => "Cannot parse", ] }, { name => "notest-test-dep", perl_mm_use_default => 0, pairs => [ "notest test CPAN::Test::Dummy::Perl5::Build::DepeFails" => join ("", "Running\\sBuild\\sfor[\\s\\S]+", "Skipping test because of notest pragma[\\s\\S]+", "Skipping test because of notest pragma[\\s\\S]+", ), ] }, { name => "recommends", tabu => ["CPAN::Test::Dummy::Perl5::Make::CircularPrereq"], perl_mm_use_default => 0, pairs => [ "o conf recommends_policy 1" => ".", "test CPAN::Test::Dummy::Perl5::Make::OptionalPrereq" => join ("", "Running\\smake\\sfor\\sA/AN/ANDK/CPAN-Test-Dummy-Perl5-Make-OptionalPrereq[\\s\\S]+", "Circular.+?requires,optional[\\s\\S]+", "00_load.t.+?ok[\\s\\S]+", "Running\\smake\\sfor\\sA/AN/ANDK/CPAN-Test-Dummy-Perl5-Make-CircularPrereq[\\s\\S]+", "00_load.t.+?ok[\\s\\S]+", ), ] }, { name => "simple make call on a configure_requires", perl_mm_use_default => 0, pairs => [ "make CPAN::Test::Dummy::Perl5::Make::ConfReq" => "make(?:\\.exe)? -- OK", ] }, { name => "rm while degraded", perl_mm_use_default => 0, pairs => [ "test CPAN::Test::Dummy::Perl5::Make" => "00_load.t\\b.*\\bok", "test CPAN::Test::Dummy::Perl5::Make" => "Has already been tested successfully", "! print \$::tmp_build_dir=CPAN::Shell->expand('Module','CPAN::Test::Dummy::Perl5::Make')->distribution->{build_dir}, \$/" => ".", "! use File::Path qw(rmtree); rmtree \$::tmp_build_dir, 0; print 'rmtreeed',\$/" => "rmtreeed", "test CPAN::Test::Dummy::Perl5::Make" => "00_load.t\\b.*\\bok", "force test CPAN::Test::Dummy::Perl5::Make" => "00_load.t\\b.*\\bok", ] }, { name => "urllist empty", perl_mm_use_default => 0, requires => [qw(Expect)], pairs => [ "o conf connect_to_internet_ok 0" => ".", "o conf urllist pop" => ".", "o conf urllist" => "urllist\\s+Type.+all configuration items", "test CPAN::Test::Dummy::Perl5::Make" => "Client not fully configured", "o conf init urllist\nn\nn\nhttp://cpan.example.com/\n\n" => "enter your CPAN[\\s\\S]+Enter another URL[\\s\\S]+New urllist\\s+http://cpan.example.com/", ] }, { name => "unambiguous regexps", pairs => [ "d /CPAN-Test-Dummy-Perl5-Make-1/" => "Distribution id = A/AN/ANDK/CPAN-Test-Dummy-Perl5-Make-1", "test /CPAN-Test-Dummy-Perl5-Make-1/" => "test -- OK", "test /CPAN-Test-Dummy-Perl5/" => "Sorry, test with a regular", ]}, { name => "reordering urllist", perl_mm_use_default => 0, gets_mirrored_by => 1, pairs => [ "o conf connect_to_internet_ok 0" => ".", "o conf urllist ONE TWO THREE FOUR" => ".", # we are asked if using the found urllist is ok, we say # yes, then we say 8 for the previous picks, then we pick # items 4 and 2 in that order "o conf init urllist\nn\ny\nt\n8\n4 2\n" => "New urllist\\s+FOUR\\s+TWO", ] }, { name => "the historically first", perl_mm_use_default => 1, pairs => [ "dump \$::x=4*6+1" => "= 25;", "dump \$::x=40*6+1" => "= 241;", "dump \$::x=40*60+1" => "= 2401;", "o conf init" => "commit: wrote", "o conf patch ' '" => ".", # prevent that C:T:D:P:B:Fails succeeds by patching "test CPAN::Test::Dummy::Perl5::Make" => "t/00_load\.+ok", "get CPAN::Test::Dummy::Perl5::Make" => "Has already been unwrapped", "make CPAN::Test::Dummy::Perl5::Make" => "(?sx:Has.already.been.unwrapped.* Has.already.been.made)", "test CPAN::Test::Dummy::Perl5::Make" => "(?sx:Has.already.been.unwrapped.* Has.already.been.made.* Has.already.been.tested.successfully)", "force test CPAN::Test::Dummy::Perl5::Make" => "t/00_load\.+ok", "test CPAN::Test::Dummy::Perl5::Build::Fails" => "(?i:t/00_load.+FAILED)", "test CPAN::Test::Dummy::Perl5::Build::Fails" => "(?i:t/00_load.+FAILED)", "get CPAN::Test::Dummy::Perl5::Build::Fails" => "Has already been unwrapped", "make CPAN::Test::Dummy::Perl5::Build::Fails" => "(?sx:Has.already.been.unwrapped.* Has.already.been.made)", "force get CPAN::Test::Dummy::Perl5::Build::Fails" => "(?sx:security.checks.disabled |Checksum.for.*CPAN-Test-Dummy-Perl5-Build-Fails-1.03.tar.gz.ok)", "o conf build_dir_reuse 1" => "build_dir_reuse", "o conf commit" => "commit: wrote", ] }, { name => "the historically second", perl_mm_use_default => 1, pairs => [ "get CPAN::Test::Dummy::Perl5::Make" => "Has already been unwrapped", "make CPAN/Test/Dummy/Perl5/Make.pm" => "(?sx:Has.already.been.unwrapped.* Has.already.been.made)", "test CPAN::Test::Dummy::Perl5::Make" => "(?sx:Has.already.been.unwrapped.* Has.already.been.made.* Has.already.been.tested.successfully)", "get CPAN::Test::Dummy::Perl5::Build::Fails" => "Has already been unwrapped", "make CPAN::Test::Dummy::Perl5::Build::Fails" => "Has.already.been.unwrapped", "test CPAN::Test::Dummy::Perl5::Build::Fails" => "(?i:t/00_load.+FAILED)", "o conf dontload_list push YAML" => ".", "o conf dontload_list push YAML::Syck" => ".", "o conf dontload_list push Parse::CPAN::Meta" => ".", "o conf dontload_list push CPAN::Meta" => ".", "o conf commit" => "commit: wrote", ] }, { name => "after we turned off yaml with dontload", perl_mm_use_default => 1, pairs => [ # Note: I had C<cannot.parse.*> also here (for FTPstats) but # this does not come under some currently unknown circumstances "get CPAN::Test::Dummy::Perl5::Make" => "(?sx: not.installed,.falling.back.* will.not.store.persistent.state)", "make CPAN::Test::Dummy::Perl5::Make" => "Falling back to other methods to determine prerequisites", "test CPAN::Test::Dummy::Perl5::Make" => "All tests successful", "clean CPAN::Test::Dummy::Perl5::Make" => "clean.*-- OK", ] }, { name => "focussing test circdepe", perl_mm_use_default => 1, pairs => [ "dump \$::x=4*6+1" => "= 25;", "test CPAN::Test::Dummy::Perl5::Make::CircDepeOne" => "(?xs: Running.test.for.module.+CPAN::Test::Dummy::Perl5::Make::CircDepeOne.+ CPAN::Test::Dummy::Perl5::Make::CircDepeThree.+\\[requires\\].+ CPAN::Test::Dummy::Perl5::Make::CircDepeTwo.+\\[requires\\].+ CPAN::Test::Dummy::Perl5::Make::CircDepeOne.+\\[requires\\].+ Recursive.dependency.detected )", ], }, { name => "focussing test unsatprereq", perl_mm_use_default => 1, pairs => [ "dump \$::x=4*6+1" => "= 25;", "test CPAN::Test::Dummy::Perl5::Make::UnsatPrereq" => "(?xs: Warning:.+? Prerequisite.+? CPAN::Test::Dummy::Perl5::Make.+? 99999999.99.+? not[ ]available[ ]according[ ]to[ ]the[ ]ind )", ], }, { name => "halt_on_failure", perl_mm_use_default => 1, pairs => [ "dump \$::x=4*6+1" => "= 25;", "o conf halt_on_failure 1" => "1", "test CPAN::Test::Dummy::Perl5::Build::Fails CPAN::Test::Dummy::Perl5::Make::Failearly" => "FAIL", # must not see Failearly in the failed summary "failed" => q{(?x:Failed \s during \s this \s session: \s+ \S+ Build-Fails \S+: \s+ make_test \s+ NO \s*\z)}, "o conf dontload_list pop" => ".", "o conf dontload_list pop" => ".", "o conf dontload_list pop" => ".", "o conf dontload_list pop" => ".", "o conf commit" => "commit: wrote", ], }, { # loads distroprefs for the C:T:D:P:M:Features module where # we demand the feature "rice". this feature then requires # CPAN::Test::Dummy::Perl5::Build which we do not have so we # build it first and then C:T:D:P:M:Features can also be # built name => "optional_features", perl_mm_use_default => 1, pairs => [ "dump \$::x=6*6+9" => "= 45;", "o conf build_dir" => "build_dir", "o conf prefs_dir '$cwd/t/dot-cpan-$$/prefs'" => "(?m:prefs_dir.+prefs)", "test CPAN::Test::Dummy::Perl5::Make::Features" => "(?sx:Builds.rice.+ ANDK/CPAN-Test-Dummy-Perl5-Build-\\d.+ \\./Build[ ]test[ ]--[ ]OK.+ ANDK/CPAN-Test-Dummy-Perl5-Make-Features-\\d.+ make\\S*[ ]test[ ]--[ ]OK)", ] }, { name => "configure_requires", perl_mm_use_default => 1, pairs => [ "test CPAN::Test::Dummy::Perl5::Make::ConfReq" => "test.*-- OK", "clean CPAN::Test::Dummy::Perl5::Make::ConfReq" => "clean.*-- OK", "clean CPAN::Test::Dummy::Perl5::Make" => "clean.*-- OK", ] }, { name => "ls", perl_mm_use_default => 1, requires => [qw(Text::Glob)], pairs => [ "ls ANDK/patches" => "-SADAHIRO-", "ls ANDK/patches/" => "-SADAHIRO-", "ls ANDK/pa*/*SADA*" => "-SADAHIRO-", "ls ANDK/patches/*SADA*" => "-SADAHIRO-", ] }, ); SESSION_CNT: for my $session (@SESSIONS) { if (%limit_to_sessions) { next SESSION_CNT unless $limit_to_sessions{$session->{name}}; } $cnt++; if (my $requires = $session->{requires}) { for my $req (@$requires) { unless ($CPAN::META->has_inst($req)) { $session->{name} .= " [skipping because $req missing]"; $session->{pairs} = []; } } } for (my $i = 0; $i<$#{$session->{pairs}}; $i+=2) { $cnt++; } } plan tests => $cnt + 1 # the MyConfig verification ; $prompt_re = "\\ncpan(?:[^>]*)> "; print "# cnt[$cnt]prompt_re[$prompt_re]\n"; } is($CPAN::Config->{'7yYQS7'} => 'vGcVJQ'); our $VERBOSE = $ENV{VERBOSE} || 0; my $devnull = File::Spec->devnull; SESSION_RUN: for my $si (0..$#SESSIONS) { my $session = $SESSIONS[$si]; if (%limit_to_sessions) { next SESSION_RUN unless $limit_to_sessions{$session->{name}}; } if (my $tabu = $session->{tabu}) { my $skip; SKIP: for my $t (@$tabu) { if ($CPAN::META->has_inst($t)) { $skip=1; my $tests = scalar(@{$session->{pairs}})/2 + 1; skip "skipping test '$session->{name}' because '$t' installed", $tests; } } next SESSION_RUN if $skip; } my $system = $session->{system} || $default_system; # warn "# DEBUG: name[$session->{name}]system[$system]"; ok($session->{name}, "opening new session '$session->{name}'"); delete $ENV{PERL_MM_USE_DEFAULT}; $ENV{PERL_MM_USE_DEFAULT} = 1 if $session->{perl_mm_use_default}; if ($session->{gets_mirrored_by}) { cp _f"t/CPAN/TestMirroredBy", _f"t/dot-cpan-$$/sources/MIRRORED.BY" or die "Could not cp t/CPAN/TestMirroredBy over t/dor-cpan/sources/MIRRORED.BY: $!"; # fix timestamp "bug" (?) on Win32 utime( (time) x 2, _f"t/dot-cpan-$$/sources/MIRRORED.BY" ); } else { unlink _f"t/dot-cpan-$$/sources/MIRRORED.BY"; } local *SYSTEM; open SYSTEM, "| $system 2> $devnull" or die "Could not open '| $system': $!"; for (my $i = 0; 2*$i < $#{$session->{pairs}}; $i++) { my($command) = $session->{pairs}[2*$i]; print SYSTEM $command, "\n"; } close SYSTEM or mydiag "error while running '$system' on '$session->{name}': $!"; my $content = do {local *FH; open FH, "test-$$.out" or die; local $/; <FH>}; my(@chunks) = split /$prompt_re/, $content; diag sprintf "DEBUG: All chunks of new session\n%s", YAML::Syck::Dump(@chunks) if $Opt{debug}; if ($Opt{pause}) { diag "Press ENTER to continue"; <>; } # shift @chunks; # warn sprintf "# DEBUG: pairs[%d]chunks[%d]", scalar @{$session->{pairs}}, scalar @chunks; for (my $i = 0; 2*$i < $#{$session->{pairs}}; $i++) { my($command) = $session->{pairs}[2*$i]; my($expect) = $session->{pairs}[2*$i+1]; my($actual) = $chunks[$i+1]; $actual =~ s{t\\00}{t/00}g if ($^O eq 'MSWin32'); if ($VERBOSE) { diag("cmd[$command]expect[$expect]actual[$actual]"); } if ($Opt{verbose}) { diag $actual; } my $success = like($actual,"/$expect/","cmd[$command]"); if (!$success) { require Dumpvalue; my $dumper = Dumpvalue->new(); my $i0 = $i > 4 ? $i-5 : 0; warn join "", map { "##$si($session->{name})/$_\:{q[". $dumper->stringify($session->{pairs}[2*$_]). "]=>q[". $dumper->stringify($chunks[$_+1]). "]}\n" } $i0..$i; } } } # Local Variables: # mode: cperl # cperl-indent-level: 4 # End: