How Do I Test This Strange Problem

phillup on 2003-10-30T17:21:27

I know that there are several testing advocates hanging out here... perhaps one will notice my plight.

;-)

I've been using CGI::Session with a MySQL database without any problems.

I decided to change to a file based storage mechanism... and it was nice to only have to change two lines of code.

Afterwards, all of my tests passed.

Imagine my surprise when it didn't work in my HTML::Mason based application.

There is something different about my environment when running under Mason that I just haven't been able to replicate very easily in a shell.

It took me a while to track down (what I think is) the problem... and the fix is one line of code to CGI::Session::File... but, I can't seem to come up with a good way to show the error using a test.

Which is very frustrating, since I can see the error by simply tracing the code!

So... why does this run without error:

------- #! /usr/bin/perl

use strict; use warnings; use CGI::Session;

print "calling sub\n"; do_something(); print "done with sub\n";

sub do_something{ my $session = new CGI::Session("driver:File;serializer:Storable", undef, {Directory=>'/tmp/cgisession'}) || die 'Could not get new session store!'; $session->delete(); } # sub do_something -------

and changing the subroutine to this causes an error? ------- sub do_something{ my $session = new CGI::Session("driver:File;serializer:Storable", undef, {Directory=>'/tmp/cgisession'}) || die 'Could not get new session store!'; $session->delete(); # add this line to force delete to be saved prior to object destruction $session->close(); } # sub do_something

-------

All the close method does is call the destructor... yet, the destructor is called in the original routine when the $session variable goes out of scope.

Now, I can trace thru the destructor code and see that the problem occurs when trying to unlink the file... and the file was never written to begin with, so it doesn't exist. (Because it isn't written until the destructor is called or an explicit flush is called... and the delete method short circuits the process.)

But what I don't understand is... why isn't the problem always evident? Why does it show up in my Mason environment, but not my shell environment?

More importantly... how can I write a test to prove that the code is bad?

To Fix the problem, make this the second line of the remove method in Session/File.pm

return 1 if $self->{_IS_NEW};

Which notices that the session is new... and bypasses the unlink attempt since the file was never written.

P.S. I don't think the unlink code should be called as part of the close routine *and* again during the objects destruction... but, that is a different problem. The author does note that the preferred method of closing the file is to undef the object, but that still doesn't work for my Mason environment.

I'm just using the close method to demonstrate the problem... because I can't figure out a way to write a test that demonstrates what I think the real concern is... the unlinking of the non-existent file.

P.P.S. I'd like to have a test to show I'm right... for the case that I'm not! I can't be completely sure that my analysis is correct... because I can't seem to prove my case. My patch fixes my problems under Mason... but, all my tests remain unaffected... they all pass.