Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

Ovid (2709)

Ovid
  (email not shown publicly)
http://publius-ovidius.livejournal.com/
AOL IM: ovidperl (Add Buddy, Send Message)

Stuff with the Perl Foundation. A couple of patches in the Perl core. A few CPAN modules. That about sums it up.

Journal of Ovid (2709)

Tuesday October 14, 2008
04:18 AM

Localizing variables in another stack frame?

[ #37660 ]

The latest development version of Test::Aggregate is out. I've tried to be somewhat conservative about what I add to this module as my primary consideration is "ease of use". This time, I've made such an obvious change that I can't believe I didn't do it earlier.

One problem with aggregating code in Perl is the built-in globals. We're constantly admonished to localize these whenever we use them, but we see things like $| = 1 in plenty of code. If it's a small test program, this doesn't look like a bad thing, but under aggregation it, altering globals like this is a bad thing. In several of our test programs, we've deliberately localized some environment variables to avoid this, but it's important that aggregating tests be (as much as is possible) a simple matter of moving the test from the t/ directory to the aggregated directory. As a result, now when I rewrite the tests, I have this at the top of all of them:

no warnings 'uninitialized';   # I ALWAYS misspell this
local %ENV = %ENV;
local $/   = $/;
local @INC = @INC;
local %INC = %INC;
local $_   = $_;
local $|   = $|;
local %SIG = %SIG;
use warnings 'uninitialized';

I went through perlvar and tried to find the most commonly used globals for this. It's getting closer and closer to emulating separate processes for every test, without the overhead of launching separate processes. Of course, we can't go the full route of separate processes because this kills the performance benefits of aggregation, but it's a decent compromise.

However, I hate having that block of variables there. Even though this is in auto-generated code that the end user doesn't see, sometimes you need to have Test::Aggregate write out the code so you can debug it manually and having all of this code duplication is a frustration. Sure, I could use something stupid like vim folding to hide it, but what I really want is the ability to run local, eval and other bits of code in a higher stack frame. I've tried various tricks to get around this, but so far it eludes me. Is there a solution? (And haven't I asked this before? I don't see that I have, but I know it's been on my mind a number of times)

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
 Full
 Abbreviated
 Hidden
More | Login | Reply
Loading... please wait.
  • ...but how about a source filter? Filtering "$.==0" and inserting your block of localizers might work.
  • Ah, I missed that these were generated blocks.

    Goto's are evil. But this might be a place to use them, perhaps...

    Why not put them at the bottom of the file? Then stick a

    # GENERATED GOTO - Localize important perl vars
    goto LOCALIZE_VARS;
    VARS_LOCALIZED:

    at the top, and generate this at the bottom:

    goto PAST_LOCALIZERS; # so we don't change return
                                                # value of co