Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister

comment on

( [id://3333] : superdoc . print w/replies, xml ) Need Help??
Background: Recently, the perl based system I am responsible for had a production issue when new code was being rolled out. It is our desire to never fully crash due to some state information that would be lost that is too transient to effectively serialize to disk with any level of efficiency. It was decided to simply increase the amount of exception handling within the core routines, so even if an issue was encountered, it could be isolated, and even repaired while the system remained running. We have full regression and unit tests for our system, which posed an interesting problem for me. How do you run your production code, and verify that it can handle any part of it's code throwing an exception, without breaking any test after this one will run (and not modifying the code BEFORE the test is run). The solution that I came up with, is grounded in the flexibility of our testing framework, so I welcome any alternative solutions, just understand that I'm not filling you in on all the constraints I'm working within.
  • This test needs to be able to modify any method of any object within the system
  • I need to temporarily modify a method of an object during runtime
  • I need to verify the exception handler works
  • I need to verify that the logic picks up where it left off after the "bug" is fixed
  • None of the runtime changes I make to test this functionality can have any impact after on subsequent tests
Here is a code snippet to illustrate the approach I took. (keep in mind that I understand that the "eval" is not needed, I built this test to try and more accurately model my system specifically)
#!/usr/bin/perl package test_package; use strict; use warnings; sub new { return bless {}; } sub test_function { print "Original test_function! $_[1]\n"; } sub loader { eval($_[1]); warn "ERROR: $@\n" if ( $@ ); } package main; use strict; use warnings; my $counter = 0; my $f = new test_package(); $f->test_function($counter++); # 1 # "backup" the test_function method $f->loader('*test_package::new_test_function = \&test_package::test_fu +nction;'); $f->new_test_function($counter++); # Overwrite the existing "test_function" subroutine $f->loader("package test_package; sub test_function { print \"New outp +ut! \$_[1]\n\"; } 1;"); # Should see two different outputs $f->test_function($counter++); $f->new_test_function($counter++); # "Restore" the test function from it's "backup" $f->loader("*test_package::test_function = *test_package::new_test_fun +ction;"); $f->test_function($counter++);
The output looks like this:
Original test_function! 0 Original test_function! 1 Subroutine test_function redefined at (eval 2) line 1. New output! 2 Original test_function! 3 Original test_function! 4
Using this approach allowed me to do the following:
  • Copy existing function calls to a "backup" area.
  • Overwrite subroutines with that I supply
  • I can restore the system to the original state, with ease, so it won't impact subsequent tests
All in all, this approach worked for me, and although it may be common knowledge to some, it wasn't something I found documented on the web, or even within perlmonks. I hope it comes in useful in the future.

In reply to "Backing up" a subroutine during runtime. by dextius

Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":

  • Are you posting in the right place? Check out Where do I post X? to know for sure.
  • Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
    <code> <a> <b> <big> <blockquote> <br /> <dd> <dl> <dt> <em> <font> <h1> <h2> <h3> <h4> <h5> <h6> <hr /> <i> <li> <nbsp> <ol> <p> <small> <strike> <strong> <sub> <sup> <table> <td> <th> <tr> <tt> <u> <ul>
  • Snippets of code should be wrapped in <code> tags not <pre> tags. In fact, <pre> tags should generally be avoided. If they must be used, extreme care should be taken to ensure that their contents do not have long lines (<70 chars), in order to prevent horizontal scrolling (and possible janitor intervention).
  • Want more info? How to link or How to display code and escape characters are good places to start.