Today I was trying to run some Test::Class-based unit tests for a project I'm working on. This project has lots of functional tests that go through Test::WWW::Mechanize, so they run inside Apache and mod_perl.
What I was trying to do was testing the same code outside the Apache server, just as regular command-line-runnable tests. Being a Perl project, you have all the nice infrastructure already done for you, and so you can just run
make test or
Build test depending on the exact tool you're using.
However, when I run this, I got a strange error:
PERL_DL_NONLAZY=1 /usr/bin/perl "-MExtUtils::Command::MM" "-e" "test_harness(0, 'blib/lib', 'blib/arch')" t/*/*.t t/unit-tests/basic-sanity.t .. ok t/unit-tests/handler-xml.t ... Can't load '/usr/lib/perl5/auto/APR/Request/Apache2/Apache2.so' for module APR::Request::Apache2: /usr/lib/perl5/auto/APR/Request/Apache2/Apache2.so: undefined symbol: modperl_xs_sv2request_rec at /usr/lib/perl/5.10/DynaLoader.pm line 193. at /usr/lib/perl5/Apache2/Request.pm line 3 Compilation failed in require at /usr/lib/perl5/Apache2/Request.pm line 3. BEGIN failed--compilation aborted at /usr/lib/perl5/Apache2/Request.pm line 3.
The weird error is:
Can't load '/usr/lib/perl5/auto/APR/Request/Apache2/Apache2.so' for module APR::Request::Apache2: /usr/lib/perl5/auto/APR/Request/Apache2/Apache2.so: undefined symbol: modperl_xs_sv2request_rec at /usr/lib/perl/5.10/DynaLoader.pm line 193.
undefined symbol: modperl_xs_sv2request_rec.
Why is this happening?
The first hit, in particular, I have no idea what that page says, because it's Japanese, but the code blocks are clearly referring to the
PERL_DL_NONLAZY environment variable:
PERL_DL_NONLAZY Set to one to have perl resolve all undefined symbols when it loads a dynamic library. The default behaviour is to resolve symbols when they are used. Setting this variable is useful during testing of extensions as it ensures that you get an error on misspelled function names even if the test suite doesn't call it.
AFAIK, it all boils down to the
modperl_xs_sv2request_rec function not being available if your code is not running inside Apache with mod_perl loaded. So, it makes sense to run the tests with
PERL_DL_NONLAZY=0 (that is, be lazy!), like the Japanese guy suggests.
However, changing that in the Makefile incantations seems to be a Royal Pain, so I just gave prove a shot. And once more, I had the proof that
prove is just the way to run your test suite, because prove seems to be smart enough to set PERL_DL_NONLAZY automatically to zero.
So now, I'm running prove through a shell script, like this:
... BASE_DIR=<project_root> ... export CONFIG_FILE=/etc/blah-blah export WHATEVER_ELSE=... ... prove -I $BASE_DIR/lib $* $BASE_DIR/t/unit-tests
And that's it, all tests successful! o/