Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery

change perl function in runtime

by david2008 (Scribe)
on Dec 03, 2012 at 15:05 UTC ( #1006889=perlquestion: print w/replies, xml ) Need Help??
david2008 has asked for the wisdom of the Perl Monks concerning the following question:


How do i change a function of perl in runtime?
I need it for testing issues.
I have a class A with function x.
This function x calls function y.
I want to check the behavior when y crashes.
So i want to change y with the function sub {die "aaa"}, make the test and then change it back.


Replies are listed 'Best First'.
Re: change perl function in runtime
by LanX (Bishop) on Dec 03, 2012 at 15:19 UTC
    You need *globs to manipulate symbol table entries like package functions! ( see perlmod and perlsub)

    Something like this should do

    { package A; local *x = sub { die "aaa" }; #run tests ... } # &x reset after leaving block

    if you want to explicitly reset &x try to store the old coderef before.

    $old_coderef = \&x; # run tests ... # do what you want ... # (but think about the omen ;-) *x = $old_coderef;

    Cheers Rolf

      It works very well. This is real perl alchemy :-)
Re: change perl function in runtime
by space_monk (Chaplain) on Dec 03, 2012 at 15:13 UTC

    It would probably be quicker to post the class methods x and y on here and ask why they don't work. :-)

    Why doesn't function y simply log whatever it is doing through use of debug statements?

    A Monk aims to give answers to those who have none, and to learn from those who know more.

      I have to disagree with you. This is a perfectly reasonable request. In fact, this is considered a good practice for testing complex software.

      There are lots of reasons for doing things like this:

      1. You may not have control over function y
      2. It might do something that you don't want to do during testing (such as submit a credit card order...)
      3. It might take a long time to run.
      4. It might be hard to reproduce certain kinds of output.
      5. It might not be written yet, or it might have bugs of its own (simulating part of the software allows you to develop/test multiple interdependent pieces of code simultaneously).

      When's the last time you used duct tape on a duct? --Larry Wall
        Thanks for the reasons. I normally suppress things I don't want to do during a test run, but I can see your points :-)
        A Monk aims to give answers to those who have none, and to learn from those who know more.
      Actually they work till i bump on a defect.
      I test the class with a .t file, so i want to check the behavior when there is a failure.
      Currently there are no known defects so i can not simulate it if i don't change the function.
Re: change perl function in runtime
by grondilu (Friar) on Dec 03, 2012 at 15:44 UTC

    EDIT: Please ignore this message, a good answer has been given above. You can alter the symbol table with *globs

    The description does not really fit the title. In order to change a perl function in runtime, you would have to alter the symbol table. It can be done but it requires a lot of perl experience I think. Unless of course your function was defined as a reference to a function, in which case you can alter it as you would with any variable, which is trivial. Anyway I don't really see what you want to do.

    It seems to me that what you really want is to just use 'eval':

    package A; sub Y { die "aargh" } sub X { eval { Y }; if ($@) { print "humm... Y failed..." } { print "ok, no error here"; } }
      The title is fine; you have misunderstood the question. Take a look at Rolf's solution.

      When's the last time you used duct tape on a duct? --Larry Wall
Re: change perl function in runtime
by DrHyde (Prior) on Dec 05, 2012 at 11:58 UTC
    Sounds like you need to:
    • invent a time machine
    • travel back a week and a bit
    • go to my talk on unit testing at the London Perl Workshop
    and then mock function y. If all you want to do is generate a die() when you call it, then simply manipulating the symbol table as others have suggested would probably be sufficient, or you might want to use Test::MockObject. If you want to be a bit more rigourous, so that as well as testing that your code behaves correctly when 'y' dies but also test that you call y correctly, I recommend Class::Mockable and Class::Mock::Generic::InterfaceTester.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1006889]
Front-paged by Arunbear
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (5)
As of 2018-08-17 16:54 GMT
Find Nodes?
    Voting Booth?
    Asked to put a square peg in a round hole, I would:

    Results (182 votes). Check out past polls.