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.
Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
Read Where should I post X? if you're not absolutely sure you're posting in the right place.
Please read these before you post! —
Posts may use any of the Perl Monks Approved HTML tags:
- a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
| |
For: |
|
Use: |
| & | | & |
| < | | < |
| > | | > |
| [ | | [ |
| ] | | ] |
Link using PerlMonks shortcuts! What shortcuts can I use for linking?
See Writeup Formatting Tips and other pages linked from there for more info.