Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot
 
PerlMonks  

Re: Making open fail

by SilasTheMonk (Chaplain)
on Jul 03, 2010 at 12:31 UTC ( #847898=note: print w/ replies, xml ) Need Help??


in reply to Making open fail

Ikegami, I tried subs again. It's pretty close to what I had tried before, but I was trying explicitly to be as close as possible to what you suggest. The script hangs on the print/read statement without the custom "open" function running.

#!perl -w use strict; use warnings; use subs qw(open); use Errno qw(EPIPE); sub open { $! = EPIPE; warn "open faked"; return 0; } Test::subs(); exit(0); package Test; sub subs { my $string = "hello world"; local *STDIN; open(STDIN, '<', \$string) or die "open failed: $!"; binmode STDIN; while(<>) { print; } } 1

bluescreen I arrived at this situation by trying to follow best practices. 1.) opening a file should be error checked. 2.) I should use Devel::Cover to make sure that my tests provide 100% test coverage. It does seem likely that this particular call can never fail, but I still thinking the problem would be hard in some other circumstances. Also may be there could be a security hole in the perl core, which would allow hackers to generate such a situation and I want to defend my code against such known unknowns.

Actually I have had two more ideas on how to approach this. One is experimenting with

local *IO::File::open = sub {.....}
If ikegami is right that't won't work but I mean it only as indication of what I might try. I assume that this is how subs works anyway. The second idea is to use autodie. I have tried this and it works in as far as it allows me to get my test coverage up. Arguably however it is just sidestepping the problem.

Edit: Looking at the code for subs I can see why it won't work for me. It only deals with the calling package not where as I want to change how "open" works inside a package from outside.

Edit 2: My experimentation with typeglobs is failing. It does no better than the subs code above.

exp.pl
#!perl -w use warnings; use Errno qw(EPIPE); use lib qw(.); eval "use Test;"; BEGIN { *{main::open} = sub { $! = EPIPE; warn "open faked"; return 0; }; } Test::subs(); exit(0);
and Test.pm
package Test; sub subs { my $string = "hello world"; local *STDIN; open(STDIN, '<', \$string) or die "open failed: $!"; binmode STDIN; while(<>) { print; } } 1


Comment on Re: Making open fail
Select or Download Code
Re^2: Making open fail
by bluescreen (Friar) on Jul 04, 2010 at 16:03 UTC

    Although I agree that you should try to get a good coverage I wouldn't pursuit the 100% itself. Let's consider the following subroutine

    sub divide { my ($a, $b) = @_; return $a / $b; }

    You can easily create a test case and get a 100% coverage, and as you might realized the code can still fail ( if $b is 0 you'll get a "Illegal division..." ), here the 100% gives you a false sense of security. On the other hand the more tests your application has the harder it is to change it or refactor it

    My point is you shouldn't blindly follow best practices, they are just a guide not a law (use your own criteria). Don't use test coverage as a goal itself, otherwise you would end up writing code to get 100% coverage instead of writing code to perform a task

      bluescreen, I absolutely understand where you are coming from on 100% test coverage. It may be fairer to say I am experimenting with it. I have all sorts of thoughts on the subject. For a start with a new module it is straightforward, to keep the test coverage up to 100%. For an older module you can only hope to approach it aggressively. It is interesting to take a module that you regard as critical, and run Devel::Cover on it - and to compare the results with the bug list - and to ask how many of those bugs could have been avoided with better testing. When I have done that and tried to discuss the results, the responses such as they were struck me as complacent. Also I am working on restructuring and improving CGI::Application::Plugin::Authentication. As a I did not write that module originally, getting the test coverage up seems a constructive way of knowing and controlling the impact of my changes.
      On the other hand the more tests your application has the harder it is to ... refactor it
      On the contrary, the more tests you have (or rather, the better your test coverage), the *easier* it is to refactor. Refactoring should involve no changes to the code's function, and the better your test coverage, the easier it is to rearrange the code without unwittingly breaking it.

        Let's consider you write test cases for private methods, and you have a bunch of them ( test cases and private methods), and then you try to refactor and you delete some of the private methods and create new ones, in that scenario you'll have a bunch of failing test cases you will have to fix, even worst if you are refactoring not just an isolated module but a whole part of your app

        Don't get me wrong, its all about balance and putting more test cases where it worth it ( riskier code ) than just putting a lot of test cases everywhere

Re^2: Making open fail
by ikegami (Pope) on Jul 05, 2010 at 18:23 UTC
    You declare main::open (use subs qw(open);), and you define main::open, neither of which has any effect on calls to open in Test::. See the example I added to my post 8 hours before you posted for how to replace builtin open in a module without changing he module.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://847898]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (17)
As of 2014-12-18 12:30 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    Is guessing a good strategy for surviving in the IT business?





    Results (51 votes), past polls