How to unit test if "." is not on #INC? - perl

I used Module::Starter to create the skeleton of a module, and one of the test files it creates ("t/00-load.t") looks like this:
#!perl -T
use 5.006;
use strict;
use warnings FATAL => 'all';
plan tests => 1;
BEGIN {
use_ok( 'My::Module' ) || print "Bail out!\n";
}
But when I run make && make test, this test fails because turning on taint mode ("perl -T") removes "." from #INC, so that My::Module is not found. I can see the value of turning on taint checking in general, but how am I supposed to then test this code? This is the error message that's output:
# Failed test 'use My::Module;'
# at t/00-load.t line 10.
# Tried to use 'My::Module'.
# Error: Can't locate My/Module.pm in #INC (#INC contains:
# /Library/Perl/5.16/darwin-thread-multi-2level
# /Library/Perl/5.16
# /Network/Library/Perl/5.16/darwin-thread-multi-2level
# /Network/Library/Perl/5.16
# /Library/Perl/Updates/5.16.2/darwin-thread-multi-2level
# /Library/Perl/Updates/5.16.2
# /System/Library/Perl/5.16/darwin-thread-multi-2level
# /System/Library/Perl/5.16
# /System/Library/Perl/Extras/5.16/darwin-thread-multi-2level
# /System/Library/Perl/Extras/5.16) at (eval 4) line 2.
# BEGIN failed--compilation aborted at (eval 4) line 2.
This is on perl 5.16.1, with Module::Starter 1.62 and ExtUtils::MakeMaker 6.86. The skeleton was created with "module-starter --module=My::Module", so using defaults for everything else.

When the module is created with Module::Starter, which in turn relies on MakeMaker (or Module::Build), then all building and testing should be done via the provided Makefile (or Build file, if using Module::Build). I.e., with make && make test or ./Build && ./Build test.

Related

Why does "Can not locate Debconf / Log.pm in #INC" issue? I just modified /usr/bin/perl into the perl that I installed

The system is Ubuntu. There is a perl in /usr/bin/, and is version is 5.18.2.
In this state, I tried to install many software by "sudo apt-get install **" and it was OK.
But a few days before, I installed a new perl in an other
directory(/share/Software/perl-5.26.0/bin/perl). And I remove the original perl then link the new perl to /use/bin/. The commands are:
sudo mv /usr/bin/perl /usr/bin/old/; (the old/ directory was make before)
sudo ln -s /share/Software/perl-5.26.0/bin/perl /usr/bin/perl
After that, I got the error informations when I install system software by apt-get. The error likes below:
1 not fully installed or removed.
After this operation, 0 B of additional disk space will be used.
Do you want to continue? [Y/n] y
debconf: Perl may be unconfigured (Can't locate Debconf/Log.pm in #INC (you may need to install the Debconf::Log module) (#INC contains: /share/Software/perl-5.26.0/lib/site_perl/5.26.0/x86_64-linux /share/Software/perl-5.26.0/lib/site_perl/5.26.0 /share/Software/perl-5.26.0/lib/5.26.0/x86_64-linux /share/Software/perl-5.26.0/lib/5.26.0) at (eval 1) line 4.
BEGIN failed--compilation aborted at (eval 1) line 4.
) -- aborting
Setting up doc-base (0.10.5) ...
Can't locate Debian/DocBase/Common.pm in #INC (you may need to install the Debian::DocBase::Common module) (#INC contains: /share/Software/perl-5.26.0/lib/site_perl/5.26.0/x86_64-linux /share/Software/perl-5.26.0/lib/site_perl/5.26.0 /share/Software/perl-5.26.0/lib/5.26.0/x86_64-linux /share/Software/perl-5.26.0/lib/5.26.0) at /usr/sbin/install-docs line 8.
BEGIN failed--compilation aborted at /usr/sbin/install-docs line 8.
Some software can be installed successfully, but some can not be.
If I put perl back to the previous, it is normal again. (That must be!)
Module "Debconf::Log" is located at /share/Software/perl-5.26.0/lib/perl5, but I can not find Debian/DocBase/Common.pm.
Path of /share/Software/perl-5.26.0/lib/perl5 is inside #INC of perl. Why it can not find it?
I even think that it is the problem when perl installed. I get below error when perl installed: ("make test")
Useless use of single ref constructor in void context at op/gv.t line 1191.
In file included from ../../../../perl.h:5644:0,
from ExtTest.xs:2:
ExtTest.c: In function ‘XS_ExtTest_constant’:
../../../../embed.h:691:40: warning: ‘pv’ may be used uninitialized in this function [-Wmaybe-uninitialized]
#define sv_setpvn(a,b,c) Perl_sv_setpvn(aTHX_ a,b,c)
^
ExtTest.xs:420:14: note: ‘pv’ was declared here
const char *pv;
^
In file included from ../../../../perl.h:5644:0,
from ExtTest.xs:2:
../../../../embed.h:691:40: warning: ‘iv’ may be used uninitialized in this function [-Wmaybe-uninitialized]
#define sv_setpvn(a,b,c) Perl_sv_setpvn(aTHX_ a,b,c)
^
ExtTest.xs:418:6: note: ‘iv’ was declared here
IV iv;
^
In file included from ../../../../perl.h:5644:0,
from ExtTest.xs:2:
ExtTest.c: In function ‘XS_ExtTest_constant’:
../../../../embed.h:691:40: warning: ‘pv’ may be used uninitialized in this function [-Wmaybe-uninitialized]
#define sv_setpvn(a,b,c) Perl_sv_setpvn(aTHX_ a,b,c)
^
ExtTest.xs:194:14: note: ‘pv’ was declared here
const char *pv;
^
In file included from ../../../../perl.h:5644:0,
from ExtTest.xs:2:
ExtTest.c: In function ‘XS_ExtTest_constant’:
../../../../embed.h:675:42: warning: ‘iv’ may be used uninitialized in this function [-Wmaybe-uninitialized]
#define sv_setiv_mg(a,b) Perl_sv_setiv_mg(aTHX_ a,b)
^
ExtTest.xs:166:6: note: ‘iv’ was declared here
IV iv;
^
# Failed test 'cp updated mtime'
# at t/cp.t line 26.
# '38'
# <=
# '1'
# Looks like you failed 1 test of 1.
Request to remove file /share/Software/perl-5.26.0-src/cpan/File-Temp/suffixOEXZVr.dat could not be completed since it is not there!
at t/mktemp.t line 75.
# parser guessed wrong encoding expected 'CP1252' got 'UTF-8'
# Failed test 'File 1 atime set correctly'
# at t/utime.t line 113.
# '37.684463262558'
# <
# '0.1'
# Failed test 'File 1 mtime set correctly'
# at t/utime.t line 114.
# '37.684463262558'
# <
# '0.1'
# Failed test 'File 2 atime set correctly'
# at t/utime.t line 118.
# '37.684463262558'
# <
# '0.1'
# Failed test 'File 2 mtime set correctly'
# at t/utime.t line 119.
# '37.684463262558'
# <
# '0.1'
# Looks like you failed 4 tests of 18.
Can't open copy1-87150: Permission denied at ../lib/File/Copy.t line 326.
# Looks like your test exited with 13 just after 366.
Failed 3 tests out of 2449, 99.88% okay.
### Since not all tests were successful, you may want to run some of
### them individually and examine any diagnostic messages they produce.
### See the INSTALL document's section on "make test".
### You have a good chance to get more information by running
### ./perl harness
### in the 't' directory since most (>=80%) of the tests succeeded.
### You may have to set your dynamic library search path,
### LD_LIBRARY_PATH, to point to the build directory:
### setenv LD_LIBRARY_PATH `pwd`:$LD_LIBRARY_PATH; cd t; ./perl harness
### LD_LIBRARY_PATH=`pwd`:$LD_LIBRARY_PATH; export LD_LIBRARY_PATH; cd t; ./perl harness
### export LD_LIBRARY_PATH=`pwd`:$LD_LIBRARY_PATH; cd t; ./perl harness
### for csh-style shells, like tcsh; or for traditional/modern
### Bourne-style shells, like bash, ksh, and zsh, respectively.
make: *** [test] Error 1
Each Perl is compiled with a few #INC directories where it will search for modules. The error message explains which directories are searched:
#INC contains:
/share/Software/perl-5.26.0/lib/site_perl/5.26.0/x86_64-linux
/share/Software/perl-5.26.0/lib/site_perl/5.26.0
/share/Software/perl-5.26.0/lib/5.26.0/x86_64-linux
/share/Software/perl-5.26.0/lib/5.26.0
This does not include the directories where APT has installed modules for Perl, e.g. under /usr/lib.
However, adding those directories will not help. Some modules are compiled for a specific Perl versions. You cannot upgrade Perl in-place, but would have to reinstall all modules. Since APT contains pre-built modules you cannot use modules installed via APT with a custom Perl.
Therefore: leave the system Perl because Ubuntu depends on its proper functioning. It is safe to install another Perl alongside, e.g. via perlbrew. It is safe to add a custom Perl to your PATH, e.g. via perlbrew switch. This will also fix a couple of additional environment variables that are required for a second Perl to work.

Perl Module::Build test run cannot find dynamically loaded module

I am building a Perl module using Module::Build. The Build.PL file is below:
use strict ;
use warnings ;
use Module::Build;
my $build = Module::Build->new
(
module_name => 'Company::LDAP::SyncAttr',
license => 'perl',
installdirs => 'vendor',
install_path => {
'bin' => '/usr/bin',
'script' => '/usr/bin'
},
) ;
$build->create_build_script ;
The module itself is here:
# SyncAttr.pm
package Company::LDAP::SyncAttr;
use Authen::Krb5;
1;
I have a test file in t/test.t that looks like this:
# test.t
use Company::LDAP::SyncAttr;
When I run ./Build test I get this error:
t/test.t .. Can't load '/usr/lib/x86_64-linux-gnu/perl5/5.20/auto/Authen/Krb5/Krb5.so' for module Authen::Krb5: /usr/lib/x86_64-linux-gnu/perl5/5.20/auto/Authen/Krb5/Krb5.so:
undefined symbol: krb5_free_krbhst at /usr/lib/x86_64-linux-gnu/perl/5.20/DynaLoader.pm line 187.
at /tmp/gg/blib/lib/Company/LDAP/SyncAttr.pm line 3.
Compilation failed in require at /tmp/gg/blib/lib/Company/LDAP/SyncAttr.pm line 3.
If I run the test.t file directly, I get no such error:
perl -Ilib/ t/test.t
What do I have to do to get ./Build test to not error out?
UPDATE: The problem lies with Module::Build. There is a routine do_tests in the Module::Build::Base module that forces the environment variable PERL_DL_NONLAZY to 1. If I change that line to set PERL_DL_NONLAZY to 0, then the tests all pass. The module Module::Build::Base does not provide an option to not set PERL_DL_NONLAZY, so I have submitted a bug report asking them add such an option. In the meantime, I will just have to skip running ./Build test.

Installed module not found when running program

Context
Here is a perl test script, in which I wanted to see how you can use a specific event loop with AnyEvent :
# file test.pl :
#!/usr/bin/perl
use strict;
use warnings;
use AnyEvent;
use AnyEvent::Impl::EV;
my $cv = AnyEvent->condvar;
my $wait_one_and_a_half_seconds = AnyEvent->timer (
after => 0.5, # after how many seconds to invoke the cb?
cb => sub { # the callback to invoke
print ("Hello from callback\n");
$cv->send;
},
);
# now wait till our time has come
$cv->recv;
Problem
Here is the error I get when running the above code :
$ perl test.pl
Can't locate EV.pm in #INC (you may need to install the EV module) (#INC
contains: /etc/perl /usr/local/lib/perl/5.18.2 /usr/local/share/perl/5.18.2
/usr/lib/perl5 /usr/share/perl5 /usr/lib/perl/5.18 /usr/share/perl/5.18
/usr/local/lib/site_perl .) at /usr/local/lib/perl/5.18.2/AnyEvent/Impl/EV.pm
line 28.
BEGIN failed--compilation aborted at /usr/local/lib/perl/5.18.2/AnyEvent/Impl/EV.pm line 28.
Compilation failed in require at test.pl line 6.
BEGIN failed--compilation aborted at test.pl line 6.
Yet I installed the AnyEvent package using cpanm, and the AnyEvent/Impl/EV.pm file is present in one of the #INC path :
$ ls /usr/local/lib/perl/5.18.2/AnyEvent/Impl/
Cocoa.pm Event.pm FLTK.pm IOAsync.pm Perl.pm Qt.pm UV.pm
EventLib.pm EV.pm Glib.pm Irssi.pm POE.pm Tk.pm
Question
How do I fix this ?
Extra remark
The error message says it is looking for EV.pm, but I would have expected AnyEvent/Impl/EV.pm.
How come the use AnyEvent::Impl::EV; I wrote got turned into perl is looking for EV.pm at runtime ?
Just tried to reproduce this with cpan install AnyEvent and can confirm I get the same error.
Line 28 of 'EV.pm' is use EV 4.00;. Your use EV; is a bit of a red herring - that's not the source of the error. This module explicitly includes a 'use' line (which frankly is a bit wierd, it's 'using' itself it seems?)
I don't think that's ever going to work, unless the #INC path is changed - I can only assume that the loading of this module is handled elsewhere, without deconstructing source code.
Referencing the man page - this module gets loaded automatically as required. So you probably don't need to use it in the first place.
Edit: Just compared perl versions. Perl 5.8.5 shows the same behaviour. My 5.20.1 install doesn't.
I'm not sure upgrading perl is necessarily the right step, but it might be worth trying? I'll try and figure out why 5.20.1 works though. It's got to be something to do with handling of #INC.
Edit:
"The handling of return values of #INC filters (subroutines returned by subroutines in #INC) has been fixed in various ways. Previously tied variables were mishandled, and setting $_ to a reference or typeglob could result in crashes."
http://perldoc.perl.org/perl5200delta.html
I think that might be what the problem is.
You're certainly not alone in having this:
http://www.cpantesters.org/cpan/report/d5939816-a510-11e0-bd04-22322d9f2468
From:
http://cpansearch.perl.org/src/MLEHMANN/AnyEvent-7.08/Changes
5.29 Sun Dec 5 10:49:21 CET 2010
- convert EV backend to EV 4.00 API (so better upgrade EV too).
The error message was actually a very correct and forward pointer to what should be done : there is an EV package which needs to be installed separately :
$ sudo cpanm EV
--> Working on EV
Fetching http://www.cpan.org/authors/id/M/ML/MLEHMANN/EV-4.18.tar.gz ... OK
Configuring EV-4.18 ... OK
Building and testing EV-4.18 ... OK
Successfully installed EV-4.18
1 distribution installed
After that, everything works :
$ cat test.pl
#!/usr/bin/perl
use strict;
use warnings;
use AnyEvent;
use EV;
my $wait_one_and_a_half_seconds = AnyEvent->timer (
after => 0.5, # after how many seconds to invoke the cb?
cb => sub { # the callback to invoke
print ("Hello from callback\n");
},
);
# now wait till our time has come
EV::run();
$ perl test.pl
Hello from callback

What's wrong with this Perl module?

I am making a very, very simple module (it is the first I've ever wrote):
package Master::Math;
use 5.12.4;
use strict;
use warnings;
require Exporter;
our #ISA = qw(Exporter)
our %EXPORT_TAGS = (
'all' => [ qw(
max
=cut
1; # End of Master::Math
When I run use this in my program, I get the error
Invalid version format (non-numeric data) at C:/Perl/lib/Master/Math.pm line 3,
near "package Master::Math
"
syntax error at C:/Perl/lib/Master/Math.pm line 3, near "package Master::Math
require Exporter"
Compilation failed in require at C:\MainDev\myperl\max.pl line 3.
BEGIN failed--compilation aborted at C:\MainDev\myperl\max.pl line 3.
What do I need to fix this? Thanks!
You're missing a semicolon on the declaration of #ISA.
In sub max, $foo is undeclared; use foreach my $foo ....
That should get it to compile. I haven't looked beyond that.
(BTW, I didn't get the same errors you did. I used perl 5.14.0, perl -cw master-math.pm.)

Why does a module compile by itself but fail when used from elsewhere?

I have a Perl module that appears to compile fine by itself, but is causing other programs to fail compilation when it is included:
me#host:~/code $ perl -c -Imodules modules/Rebat/Store.pm
modules/Rebat/Store.pm syntax OK
me#host:~/code $ perl -c -Imodules bin/rebat-report-status
Attempt to reload Rebat/Store.pm aborted
Compilation failed in require at bin/rebat-report-status line 4.
BEGIN failed--compilation aborted at bin/rebat-report-status line 4.
The first few lines of rebat-report-status are
...
3 use Rebat;
4 use Rebat::Store;
5 use strict;
...
Edit (for posterity): Another reason for this to occur, and perhaps the most common reason, is that there is a circular dependency among the modules you are using.
Look in Rebat/Store.pm for clues. Your log says attempt to reload was aborted. Maybe Rebat already imports Rebat::Store, and Rebat::Store has some package-scope check against being loaded twice.
This code demonstrates the kind of situation I mean:
# m1.pl:
use M1;
use M1::M2;
M1::M2::x();
# M1.pm
package M1;
use M1::M2;
1;
# M1/M2.pm
package M1::M2;
our $imported = 0;
sub import {
die "Attempt to reload M1::M2 aborted.\n" if $imported++;
}
sub x { print "42\n" }
1;
$ perl m1.pl
Attempt to reload M1::M2 aborted.
BEGIN failed--compilation aborted at m1.pl line 3.
The code will compile (and print 42) if you just remove the use M1::M2 line in m1.pl. In your case, you might not need to explicitly use Rebat::Store in your program.
perldoc perldiag:
Attempt to reload %s aborted.
(F) You tried to load a file with "use" or "require" that failed to
compile once already. Perl will not try to compile this file again
unless you delete its entry from %INC. See "require" in perlfunc
and "%INC" in perlvar.