Re: Mock::Socket and the Essentials of Testing libnet
In article <20011021000950.I588@blackrider>, "Michael G Schwern" <[EMAIL PROTECTED]> wrote: > For libnet it happens to work out that the untestable part (the network > connection) is incidental. The testable part (the protocol) is essential. > That's the sweet spot. If we can seperate the net connection from the > protocol, we've got it made. No need for elaborate skip tests and assumptions > about platforms. chromatic did just that. Er, actually, chromatic just fat-fingered Socket::inet_ntoa() and Socket::inet_aton(). (Yeah, they don't really require nameservers. No, the real ones don't resolve names to packed addresses. Hey, it's a *feature* that you can send bad data in the test and still test the module. That's how powerful Mock Objects are.) While my heart's definitely in the right place, I pulled a Homer on this one. Thanks, though. So far, I have tests for Net::Time and Net::Config. Easy stuff. > So we can test libnet. We can do it on all platforms. We don't have to muck > about with any more $^O hackery than usual. Most tests will involve writing > some sort of dummy server. For some, this will be easy (Net::Ping, Net::Time) > for others it might be hard (Net::FTP), but it's possible. Agreed. The rest of you hop to it! Please? -- c
Re: [proposed PATCH installhtml] Re: installhtml needs a good beating out
On Sat, Oct 20, 2001 at 04:25:02PM -0400, Michael G Schwern wrote: > On Sat, Oct 20, 2001 at 06:25:20PM +0300, Jarkko Hietaniemi wrote: > > You have been drinking deeply from the fount of the QA Kool-Aid, > > haven't you? I'm probably not going to be surprised one day to > > find a regression test for Configure waiting in my inbox. > > Would you mind it if you did? ;) I would suggest seeking immediate psyciathric help. -- $jhi++; # http://www.iki.fi/jhi/ # There is this special biologist word we use for 'stable'. # It is 'dead'. -- Jack Cohen
Mock::Socket and the Essentials of Testing libnet
When looking at something that's going to prove nasty to test, you can apply the same criteria as Holmes: Once we remove the untestable, what remains, however difficult, must be testable. What's the problem with testing libnet? The network connection. We can't guarantee that the machine will have the ability to produce net connections at all, whether local or remote. Ok. The second part to analyzing a nasty test case is to winnow away the unimportant bits. Parts of the process that either are incidental, or are well-tested elsewhere. Let's take something like Net::Time. What does Net::Time do? It queries servers, using a simple (but specific) protocol, to find the time of day. What's the most important part there? That you understand the protocol and get the time of day. The fact that this is done over a network is largely incidental. It's uninteresting. It's a solved problem. Let's take another, Net::FTP. It's a File Transfer Protocol. It speaks a specific set of queries and responses to send and receive files over sockets. The fact that it does this over a real network connection is not where the complexity lies. The difficult part is speaking FTP. The fact that you speak it over a network socket, a dummy object or on paper is incidental. Essentially, it's more important that it's "FTP" than that it's "Net". The libnet modules implement a series of protocols that are best used over a network but it's *not essential* that they actually travel over a network. In contrast, IO::Socket::INET is the other way around. In that case, the fact that it speaks over the Internet is central to it's purpose. For libnet it happens to work out that the untestable part (the network connection) is incidental. The testable part (the protocol) is essential. That's the sweet spot. If we can seperate the net connection from the protocol, we've got it made. No need for elaborate skip tests and assumptions about platforms. chromatic did just that. http://www.xray.mpe.mpg.de/mailing-lists/perl5-porters/2001-10/msg00837.html Employing the 7-layer burrito model of networking protocols [1], chromatic has simply pulled a switcheroo with Mock::Socket at a layer below that which libnet cares about. So Net::FTP thinks it's talking to an FTP server, when in reality it's connection has been hijacked and a dummy test server put in it's place. So we can exercise the FTP protocol without having to worry about the details of making a network connection. The essential, testable bits can be tested. The incidental, untestable bits are avoided. So we can test libnet. We can do it on all platforms. We don't have to muck about with any more $^O hackery than usual. Most tests will involve writing some sort of dummy server. For some, this will be easy (Net::Ping, Net::Time) for others it might be hard (Net::FTP), but it's possible. [1] http://www.randywanker.com/OSI/ I think I just wanted to mention the network burrito. -- Michael G. Schwern <[EMAIL PROTECTED]>http://www.pobox.com/~schwern/ Perl6 Quality Assurance <[EMAIL PROTECTED]> Kwalitee Is Job One "None of our men are "experts."... because no one ever considers himself expert if he really knows his job." -- From Henry Ford Sr., "My Life and Work," p. 86 (1922):
Re: Preliminary test coverage analysis
On Sat, Oct 20, 2001 at 10:37:01PM +0200, Paul Johnson wrote: > By the way, I got rid of perl-qa-metrics. It's basically dead, right? Basically. -- Michael G. Schwern <[EMAIL PROTECTED]>http://www.pobox.com/~schwern/ Perl6 Quality Assurance <[EMAIL PROTECTED]> Kwalitee Is Job One please remove your pants we promise this won't hurt much prepare for insertion -- Fmh
Re: [proposed PATCH installhtml] Re: installhtml needs a good beating out
On Sat, Oct 20, 2001 at 06:25:20PM +0300, Jarkko Hietaniemi wrote: > You have been drinking deeply from the fount of the QA Kool-Aid, > haven't you? I'm probably not going to be surprised one day to > find a regression test for Configure waiting in my inbox. Would you mind it if you did? ;) -- Michael G. Schwern <[EMAIL PROTECTED]>http://www.pobox.com/~schwern/ Perl6 Quality Assurance <[EMAIL PROTECTED]> Kwalitee Is Job One Any sufficiently encapsulated hack is no longer a hack.
Re: Preliminary test coverage analysis
On Thu, Oct 18, 2001 at 10:42:33PM -0400, Michael G Schwern wrote: > On Thu, Oct 18, 2001 at 12:07:26AM -0600, chromatic wrote: > > > - Of those covered, a smidge less than half have < 75% statement coverage. - " > > >" " , 20% have < 50% statement coverage. > > > > Is it possible to get an update on this? Writing a new test from > > scratch is generally harder than adding to an existing test. (It's > > probably the blank page thing that plagues authors.) > > Unfortunately, no. Devel::Coverage is fundamentally broken and > Devel::Cover is gagging on the core test suite. > > I'll see what I can do about getting Devel::Cover working. I started with the intention of looking at this last night but got sidetracked by the AUTOLOAD problem which is stopping Devel::Cover working with bleadperl. I'll try to look further. By the way, I got rid of perl-qa-metrics. It's basically dead, right? -- Paul Johnson - [EMAIL PROTECTED] http://www.pjcj.net
Re: installhtml needs a good beating out
On 2001.10.20 17:16 Jarkko Hietaniemi wrote: > On Sat, Oct 20, 2001 at 02:02:59AM -0400, Michael G Schwern wrote: > > > > > > I think installhtml teeters heavily on the brink of "Rewriting" > > > instead of "Refactoring". It hasn't changed much since 1997. > > > > Refactoring is just rewriting in small pieces. By doing it in small > > pieces, you have a much better chance of succeeding and of staying > > backwards compatible. > > We are talking about a script that is run once by the Perl > installation process, and by nobody else. There is no other backwards > compatibility than producing the right output files: it's not like we > have care about an API or the like. While we're at it : I noticed that the module Pod::Functions is used only by splitpod, that is in turn used only by installhtml. (Pod::Functions has a builtin list of all perl functions : it's only useful to split perlfunc into small pieces). But Pod::Functions is under lib/ in the source tree, and that means that it gets installed (by "make install"). This looks like a bug. Should Pod::Functions be moved under pod/ ? (And should it be removed from the untested modules list ?)
Re: [PATCH lib/Net/Config.pm, MANIFEST, t/lib/Mock/Socket.pm, lib/Net/Config.t] Add Tests for Net::Config
On Sat, Oct 20, 2001 at 12:04:49PM -0600, chromatic wrote: > On Saturday 20 October 2001 11:54, you wrote: > > > So why is this tested using a mock-up by Net::Config? Sounds like > > a job the Socket should be testing (and it is). > > Oh, no! It's not. Mock::Socket is just a dummy object with the same > interface as Socket. It lets the test control the data sent back to > Net::Config. The test doesn't care whether or not Socket works. That's > *way* out of the scope of Net::Config. The real Socket.pm should never be > loaded. Hmmm. That sounds a little bit better. > > I hope you have noticed that the baseline is rather low. > > As long as it's marked... :) As I tried to explain, it's currently not marked anywhere else than in short-lived emissions of photons as the poorly explained test failures whizz by the eyes of the person doing the build. > -- c -- $jhi++; # http://www.iki.fi/jhi/ # There is this special biologist word we use for 'stable'. # It is 'dead'. -- Jack Cohen
Re: [PATCH lib/Net/Config.pm, MANIFEST, t/lib/Mock/Socket.pm, lib/Net/Config.t] Add Tests for Net::Config
On Saturday 20 October 2001 11:54, you wrote: > So why is this tested using a mock-up by Net::Config? Sounds like > a job the Socket should be testing (and it is). Oh, no! It's not. Mock::Socket is just a dummy object with the same interface as Socket. It lets the test control the data sent back to Net::Config. The test doesn't care whether or not Socket works. That's *way* out of the scope of Net::Config. The real Socket.pm should never be loaded. (The test also doesn't care whether or not t/op/var.t fails, for example. So it's not as bad as it sounds. If most everything is properly tested in isolation, it's *much* easier to find the one broken thing.) > That the tests tells us "tests 3, 17, 18, and 22 were skipped because > you do not seem to have an environment the test expects" is a nice > tidbit for the installer to know, but will that help the users if the > matter is not permanently documented? If the detailed test results > were *recorded* somewhere in the installation, they would be much more > useful: "Note that feature blartz does not work in GoofOS, because ..." Perhaps Test::Harness should capture skip messages and append them to a POD somewhere? I'm happy to work on this if it's a good idea. "You appear to be running $^O. The following tests were skipped. This does not guarantee the modules will not run on your system, but it is a pretty good indication that you are on your own." > > The best we can do is establish a baseline of behavior that ought to work > > on all platforms. If it throws up red flags and makes someone *think* > > about > > I hope you have noticed that the baseline is rather low. As long as it's marked... :) -- c
Re: [PATCH lib/Net/Config.pm, MANIFEST, t/lib/Mock/Socket.pm, lib/Net/Config.t] Add Tests for Net::Config
> Net::Config doesn't care *how* inet_ntoa and inet_aton do their job. > It just cares that it gets data in the right format. Tying STDIN So why is this tested using a mock-up by Net::Config? Sounds like a job the Socket should be testing (and it is). > and feeding fake input to Term::Complete is, in a weird sense, much > the same thing. (Maybe that's not the right test to mention... ) :-) > It sounds like we have different ideas as to what a test suite is > supposed to prove. To me, it's a near-guarantee that as far as p5p > can control, the code appears to do what it says on your platform. I think the key is here: "on your platform". I think that for many things there's simply too much outside of our control to write any meaningful tests. A beatiful thought, but painful to execute. As an example: the Term:: tests. They practically assume a very UNIX-like environment. So if you are writing tests, you are really testing whether the environment is UNIX-like. And I do not think that is helping much. Yes, it will find the limits of UNIX compatibility: but that is the task of the documentation to tell about (thou shalt not try this unless you are UNIX). That the tests tells us "tests 3, 17, 18, and 22 were skipped because you do not seem to have an environment the test expects" is a nice tidbit for the installer to know, but will that help the users if the matter is not permanently documented? If the detailed test results were *recorded* somewhere in the installation, they would be much more useful: "Note that feature blartz does not work in GoofOS, because ..." I think that the of %Config and $^O tests in a test should be a warning flag-- what are we *really* testing? > There's definitely a range of things that cannot be tested, but it's > smaller than most people would think. We also can't mathematically > *prove* that everything works in every configuration. > > The best we can do is establish a baseline of behavior that ought to work on > all platforms. If it throws up red flags and makes someone *think* about I hope you have noticed that the baseline is rather low. -- $jhi++; # http://www.iki.fi/jhi/ # There is this special biologist word we use for 'stable'. # It is 'dead'. -- Jack Cohen
Re: [PATCH lib/Net/Config.pm, MANIFEST, t/lib/Mock/Socket.pm, lib/Net/Config.t] Add Tests for Net::Config
In article <[EMAIL PROTECTED]>, "Jarkko Hietaniemi" <[EMAIL PROTECTED]> wrote: >> In the process, with some advice from perl-qa, I've added a mock object so >> the test could control the output of Socket::inet_ntoa() and >> Socket::inet_aton(). t/lib/Mock/ seemed like as good a place as any. > I'm not convinced. By setting up mock-ups you are not testing the real thing: > you are testing mock-ups. It's real emptying shotguns at decoys and > concluding that yup, we are eating duck tonight. I see it as isolating the point of failure. If the Socket module fails, its own test should say so. Trying to write a test that takes into account all of the possible network variations is an exercise in madness. (It's probably akin to being a pumpking :). Mock objects aren't a lot different than mock input. They just seem weird because they have a different shape. They help separate the things that change (underlying network differences) from the things that stay the same (the module being tested). Net::Config doesn't care *how* inet_ntoa and inet_aton do their job. It just cares that it gets data in the right format. Tying STDIN and feeding fake input to Term::Complete is, in a weird sense, much the same thing. (Maybe that's not the right test to mention... ) > FWIW, I'm happy with leaving libnet essentially untested because I think by > its very nature it is untestable across all the possible network > configurations. Try some time using ftp from behind sadistic firewalls, for > example. Situations like this *can* be configured to work, most of the time, > but it requires a lot of off-line head scratching, bribing the keepers of the > firewalls, things like that. Things a test suite cannot do unless we make Perl > pass the Turing test. It sounds like we have different ideas as to what a test suite is supposed to prove. To me, it's a near-guarantee that as far as p5p can control, the code appears to do what it says on your platform. There's definitely a range of things that cannot be tested, but it's smaller than most people would think. We also can't mathematically *prove* that everything works in every configuration. The best we can do is establish a baseline of behavior that ought to work on all platforms. If it throws up red flags and makes someone *think* about changes to existing code, so much the better. I'm all for an 80% solution, as long as we realize that there's 20% still out there. 80% is better than 70% or 50% or 0%. > QA incendiary: I think rabidly trying to strap a test harness on everything > that moves is counterproductive. Not all APIs have been planned to be tested. > Of course the documentation should tell what are the public interfaces, but > if in doubt, *ask* the author. Testing for internal not-meant-to-be-seen bits > is plain silly. You're right -- some things shouldn't be tested (accessors!). Still, the finer-grained the tests, the easier it is to find an error. I'd rather spend my time fixing a dozen bugs, if I can pinpoint them to within five lines, than tracking down one. Of course, my opinions might change, if I have to write tests for CPAN.pm or the debugger. Yikes. -- c
[REPATCH installhtml] Re: installhtml needs a good beating out
In article <[EMAIL PROTECTED]>, "Johan Vromans" <[EMAIL PROTECTED]> wrote: > I'm not sure what you are trying to achieve with this. Really really small incremental changes? > The net efffect is that you get something like > > GetOptions('foo' => \$Options{foo}, 'bar=s' => \$Options{bar}) > > which is exactly what you get when you write > > GetOptions(\%Options, 'foo', 'bar=s') Indeed. If I were to rewrite the patch, I'd do it that way. Thank you for the sanity check! -- c --- ~installhtmlSat Oct 20 01:44:43 2001 +++ installhtml Sat Oct 20 11:08:08 2001 @@ -167,12 +167,10 @@ # See vms/descrip_mms.template -> descrip.mms for invokation. if ( $^O eq 'VMS' ) { @ARGV = split(/\s+/,$ARGV[0]); } -use vars qw($opt_htmldir $opt_htmlroot $opt_podroot $opt_splitpod -$opt_verbose $opt_help $opt_podpath $opt_splithead $opt_splititem -$opt_libpods $opt_recurse); +use vars qw( %Options ); # parse the command-line -my $result = GetOptions( qw( +my $result = GetOptions( \%Options, qw( help podpath=s podroot=s @@ -249,7 +247,7 @@ $_ =~ s{HREF="#(.*)">}{ my $url = "$file/$1.html" ; $url = Pod::Html::relativize_url( $url, "$file.html" ) -if ( ! defined $opt_htmlroot || $opt_htmlroot eq '' ) ; +if ( ! defined $Options{htmlroot} || $Options{htmlroot} eq '' ); "HREF=\"$url\">" ; }eg; push @data, $_; @@ -273,24 +271,24 @@ sub parse_command_line { -usage() if defined $opt_help; -$opt_help = "";# make -w shut up +usage() if defined $Options{help}; +$Options{help} = ""; # make -w shut up # list of directories -@podpath = split(":", $opt_podpath) if defined $opt_podpath; +@podpath = split(":", $Options{podpath}) if defined $Options{podpath}; # lists of files -@splithead = split(",", $opt_splithead) if defined $opt_splithead; -@splititem = split(",", $opt_splititem) if defined $opt_splititem; -@libpods = split(",", $opt_libpods) if defined $opt_libpods; - -$htmldir = $opt_htmldir if defined $opt_htmldir; -$htmlroot = $opt_htmlroot if defined $opt_htmlroot; -$podroot = $opt_podroot if defined $opt_podroot; -$splitpod = $opt_splitpod if defined $opt_splitpod; +@splithead = split(",", $Options{splithead}) if defined $Options{splithead}; +@splititem = split(",", $Options{splititem}) if defined $Options{splititem}; +@libpods = split(",", $Options{libpods}) if defined $Options{libpods}; + +$htmldir = $Options{htmldir} if defined $Options{htmldir}; +$htmlroot = $Options{htmlroot} if defined $Options{htmlroot}; +$podroot = $Options{podroot} if defined $Options{podroot}; +$splitpod = $Options{splitpod} if defined $Options{splitpod}; -$recurse = $opt_recurse if defined $opt_recurse; -$verbose = $opt_verbose if defined $opt_verbose; +$recurse = $Options{recurse} if defined $Options{recurse}; +$verbose = $Options{verbose} if defined $Options{verbose}; } @@ -337,7 +335,7 @@ ($lcp1,$lcp2) = ($name =~ m,/H1>\s\s(\S+)\s[\s-]*(.*?)\s*$,sm); } my $url= "$dir/$file" ; - if ( ! defined $opt_htmlroot || $opt_htmlroot eq '' ) { + if ( ! defined $Options{htmlroot} || $Options{htmlroot} eq '' ) { $url = Pod::Html::relativize_url( "$dir/$file", $html ) ; }
Re: [PATCH lib/Net/Config.pm, MANIFEST, t/lib/Mock/Socket.pm, lib/Net/Config.t] Add Tests for Net::Config
> Here's a test suite for Net::Config. In the process of writing > this, I've fixed an apparent bug that prevented single values from > becoming array references when necessary. I think it's right, but > perhaps Graham should weigh in on this. > > In the process, with some advice from perl-qa, I've added a mock > object so the test could control the output of Socket::inet_ntoa() > and Socket::inet_aton(). t/lib/Mock/ seemed like as good a place as > any. I'm not convinced. By setting up mock-ups you are not testing the real thing: you are testing mock-ups. It's real emptying shotguns at decoys and concluding that yup, we are eating duck tonight. Testing that the netconfig file works right with the %Netconfig is nice I think somewhat beside the point. The format of the file is irrelevant for the *outward* functionality of libnet. FWIW, I'm happy with leaving libnet essentially untested because I think by its very nature it is untestable across all the possible network configurations. Try some time using ftp from behind sadistic firewalls, for example. Situations like this *can* be configured to work, most of the time, but it requires a lot of off-line head scratching, bribing the keepers of the firewalls, things like that. Things a test suite cannot do unless we make Perl pass the Turing test. QA incendiary: I think rabidly trying to strap a test harness on everything that moves is counterproductive. Not all APIs have been planned to be tested. Of course the documentation should tell what are the public interfaces, but if in doubt, *ask* the author. Testing for internal not-meant-to-be-seen bits is plain silly. -- $jhi++; # http://www.iki.fi/jhi/ # There is this special biologist word we use for 'stable'. # It is 'dead'. -- Jack Cohen
Re: [proposed PATCH installhtml] Re: installhtml needs a good beating out
On Sat, Oct 20, 2001 at 01:54:14AM -0600, chromatic wrote: > In article <20011020014825.J3681@blackrider>, "Michael G Schwern" > <[EMAIL PROTECTED]> wrote: > > > Convert from $opt_* globals to an %Options hash > > A fun use of map! > > Is there a test for this beast? A quick 'perl -wc installhtml' verified that > it compiles, but refactoring's half complete without regression testing. You have been drinking deeply from the fount of the QA Kool-Aid, haven't you? I'm probably not going to be surprised one day to find a regression test for Configure waiting in my inbox. -- $jhi++; # http://www.iki.fi/jhi/ # There is this special biologist word we use for 'stable'. # It is 'dead'. -- Jack Cohen
Re: installhtml needs a good beating out
On Sat, Oct 20, 2001 at 02:02:59AM -0400, Michael G Schwern wrote: > On Sat, Oct 20, 2001 at 08:58:11AM +0300, Jarkko Hietaniemi wrote: > > > Once you've done that you can add "Refactoring" to the list of > > > buzzwords on your resume. :) > > > > I think installhtml teeters heavily on the brink of "Rewriting" > > instead of "Refactoring". It hasn't changed much since 1997. > > Refactoring is just rewriting in small pieces. By doing it in small > pieces, you have a much better chance of succeeding and of staying > backwards compatible. We are talking about a script that is run once by the Perl installation process, and by nobody else. There is no other backwards compatibility than producing the right output files: it's not like we have care about an API or the like. > If nothing else, a good scrubbing out will leave it in a sane state so > someone can fathom it more easily to do a rewrite. -- $jhi++; # http://www.iki.fi/jhi/ # There is this special biologist word we use for 'stable'. # It is 'dead'. -- Jack Cohen
Re: [proposed PATCH installhtml] Re: installhtml needs a good beating out
> # parse the command-line > -my $result = GetOptions( qw( > +my $result = GetOptions( map { > + my $key = $_; > + $key =~ s/\W.+$//; > + $key => \$Options{$_}; > +} qw( > help > podpath=s > podroot=s I'm not sure what you are trying to achieve with this. The net efffect is that you get something like GetOptions('foo' => \$Options{foo}, 'bar=s' => \$Options{bar}) which is exactly what you get when you write GetOptions(\%Options, 'foo', 'bar=s') -- Johan
[proposed PATCH installhtml] Re: installhtml needs a good beating out
In article <20011020014825.J3681@blackrider>, "Michael G Schwern" <[EMAIL PROTECTED]> wrote: > Convert from $opt_* globals to an %Options hash A fun use of map! Is there a test for this beast? A quick 'perl -wc installhtml' verified that it compiles, but refactoring's half complete without regression testing. -- c --- ~installhtmlSat Oct 20 01:44:43 2001 +++ installhtml Sat Oct 20 01:50:47 2001 @@ -167,12 +167,14 @@ # See vms/descrip_mms.template -> descrip.mms for invokation. if ( $^O eq 'VMS' ) { @ARGV = split(/\s+/,$ARGV[0]); } -use vars qw($opt_htmldir $opt_htmlroot $opt_podroot $opt_splitpod -$opt_verbose $opt_help $opt_podpath $opt_splithead $opt_splititem -$opt_libpods $opt_recurse); +use vars qw( %Options ); # parse the command-line -my $result = GetOptions( qw( +my $result = GetOptions( map { + my $key = $_; + $key =~ s/\W.+$//; + $key => \$Options{$_}; +} qw( help podpath=s podroot=s @@ -249,7 +251,7 @@ $_ =~ s{HREF="#(.*)">}{ my $url = "$file/$1.html" ; $url = Pod::Html::relativize_url( $url, "$file.html" ) -if ( ! defined $opt_htmlroot || $opt_htmlroot eq '' ) ; +if ( ! defined $Options{htmlroot} || $Options{htmlroot} eq '' ); "HREF=\"$url\">" ; }eg; push @data, $_; @@ -273,24 +275,24 @@ sub parse_command_line { -usage() if defined $opt_help; -$opt_help = "";# make -w shut up +usage() if defined $Options{help}; +$Options{help} = ""; # make -w shut up # list of directories -@podpath = split(":", $opt_podpath) if defined $opt_podpath; +@podpath = split(":", $Options{podpath}) if defined $Options{podpath}; # lists of files -@splithead = split(",", $opt_splithead) if defined $opt_splithead; -@splititem = split(",", $opt_splititem) if defined $opt_splititem; -@libpods = split(",", $opt_libpods) if defined $opt_libpods; - -$htmldir = $opt_htmldir if defined $opt_htmldir; -$htmlroot = $opt_htmlroot if defined $opt_htmlroot; -$podroot = $opt_podroot if defined $opt_podroot; -$splitpod = $opt_splitpod if defined $opt_splitpod; +@splithead = split(",", $Options{splithead}) if defined $Options{splithead}; +@splititem = split(",", $Options{splititem}) if defined $Options{splititem}; +@libpods = split(",", $Options{libpods}) if defined $Options{libpods}; + +$htmldir = $Options{htmldir} if defined $Options{htmldir}; +$htmlroot = $Options{htmlroot} if defined $Options{htmlroot}; +$podroot = $Options{podroot} if defined $Options{podroot}; +$splitpod = $Options{splitpod} if defined $Options{splitpod}; -$recurse = $opt_recurse if defined $opt_recurse; -$verbose = $opt_verbose if defined $opt_verbose; +$recurse = $Options{recurse} if defined $Options{recurse}; +$verbose = $Options{verbose} if defined $Options{verbose}; } @@ -337,7 +339,7 @@ ($lcp1,$lcp2) = ($name =~ m,/H1>\s\s(\S+)\s[\s-]*(.*?)\s*$,sm); } my $url= "$dir/$file" ; - if ( ! defined $opt_htmlroot || $opt_htmlroot eq '' ) { + if ( ! defined $Options{htmlroot} || $Options{htmlroot} eq '' ) { $url = Pod::Html::relativize_url( "$dir/$file", $html ) ; }
[PATCH lib/Net/Config.pm, MANIFEST, t/lib/Mock/Socket.pm, lib/Net/Config.t] Add Tests for Net::Config
Here's a test suite for Net::Config. In the process of writing this, I've fixed an apparent bug that prevented single values from becoming array references when necessary. I think it's right, but perhaps Graham should weigh in on this. In the process, with some advice from perl-qa, I've added a mock object so the test could control the output of Socket::inet_ntoa() and Socket::inet_aton(). t/lib/Mock/ seemed like as good a place as any. I'm happy to rework this patch if it personally offends anyone whose opinion matters. :) -- c --- lib/Net/~Config.pm Sat Oct 20 01:23:46 2001 +++ lib/Net/Config.pm Sat Oct 20 01:23:54 2001 @@ -13,7 +13,7 @@ @EXPORT = qw(%NetConfig); @ISA = qw(Net::LocalCfg Exporter); -$VERSION = "1.05"; # $Id: //depot/libnet/Net/Config.pm#9 $ +$VERSION = "1.06"; # $Id: //depot/libnet/Net/Config.pm#9 $ eval { local $SIG{__DIE__}; require Net::LocalCfg }; @@ -54,11 +54,11 @@ } my ($k,$v); while(($k,$v) = each %NetConfig) { -$v = [ $v ] - if($k =~ /_hosts$/ && !ref($v)); + $NetConfig{$k} = [ $v ] + if($k =~ /_hosts$/ && !ref($v)); } -# Take a hostname and determine if it is inside te firewall +# Take a hostname and determine if it is inside the firewall sub requires_firewall { shift; # ignore package --- ~MANIFEST Sat Oct 20 01:24:04 2001 +++ MANIFESTSat Oct 20 01:24:42 2001 @@ -1065,6 +1065,7 @@ lib/Net/Cmd.pm libnet lib/Net/Config.eg libnet lib/Net/Config.pm libnet +lib/Net/Config.pm libnet (see if Net::Config works) lib/Net/demos/ftp libnet lib/Net/demos/inetdlibnet lib/Net/demos/nntp libnet --- /dev/null Thu Aug 30 03:54:37 2001 +++ t/lib/Mock/Socket.pmSat Oct 20 00:02:49 2001 @@ -0,0 +1,31 @@ +package Mock::Socket; + +# this is not the package you're looking for + +package Socket; + +$INC{'Socket.pm'} = 1; + +use Exporter; +@Socket::ISA = ( 'Exporter' ); +@EXPORT = qw( &inet_aton &inet_ntoa ); + +my (%aton, %ntoa); + +sub set_dns { + while (my ($name, $number) = splice(@_, 0, 2)) { + my $packed = unpack( "N", pack("C*", split(/\./, $number))); + $aton{$name} = $packed; + $ntoa{$packed} = $number; + } +} + +sub inet_aton { + return $aton{$_[0]}; +} + +sub inet_ntoa { + return $ntoa{$_[0]}; +} + +1; --- /dev/null Thu Aug 30 03:54:37 2001 +++ lib/Net/Config.tSat Oct 20 01:18:50 2001 @@ -0,0 +1,85 @@ +#!./perl + +BEGIN { + chdir 't' if -d 't'; + @INC = ( 'lib', '../lib' ); +} + +# lots of magic, see t/lib/Mock/Socket +use Mock::Socket; +use Test::More tests => 14; + +use_ok( 'Net::Config' ); +ok( keys %NetConfig, '%NetConfig should be imported' ); + +undef $NetConfig{'ftp_firewall'}; +is( Net::Config->requires_firewall, 0, + 'requires_firewall() should return 0 without ftp_firewall defined' ); + +# this calls inet_aton in the mock Socket, so it *may* not be portable +$NetConfig{'ftp_firewall'} = 1; +is( Net::Config->requires_firewall, -1, + '... should return -1 without a valid hostname' ); + +# use the mock Socket to resolve addresses our way +Socket::set_dns( localhost => '127.0.0.1', remotehost => '192.168.10.0' ); +delete $NetConfig{'local_netmask'}; +is( Net::Config->requires_firewall('localhost'), 0, + '... should return 0 without local_netmask defined' ); + +# +$NetConfig{'local_netmask'} = '127.0.0.1/24'; +is( Net::Config->requires_firewall('localhost'), 0, + '... should return false if host is within netmask' ); +is( Net::Config->requires_firewall('remotehost'), 1, + '... should return true if host is outside netmask' ); + +# now try more netmasks +Socket::set_dns( otherlocal => '10.10.255.254' ); +$NetConfig{'local_netmask'} = [ '127.0.0.1/24', '10.0.0.0/8' ]; +is( Net::Config->requires_firewall('otherlocal'), 0, + '... should find success with mutiple local netmasks' ); +is( Net::Config->requires_firewall('remotehost'), 1, + '... should handle failure with multiple local netmasks' ); + +# now fool Perl into compiling this again. HEY, LOOK OVER THERE! +my $path = $INC{'Net/Config.pm'}; +delete $INC{'Net/Config.pm'}; + +# Net::Config populates %NetConfig from 'libnet.cfg', if possible +my $wrote_file = 0; + +(my $cfgfile = $path) =~ s/Config.pm/libnet.cfg/; +if (open(OUT, '>' . $cfgfile)) { + use Data::Dumper; + print OUT Dumper({ + some_hosts => [ 1, 2, 3 ], + time_hosts => 'abc', + some_value => 11, + }); + close OUT; + $wrote_file = 1; +} + +SKIP: { + skip('could not write cfg file', 4) unless $wrote_file; + + # and here comes Net::Config, again! no import() necessary + require $path; + + is( $NetConfig{some_value}, 11, + 'Net::Config should populate %NetConfig from libnet.cfg file' ); + is( scalar @{ $NetConfig{time_hosts} }, 1, + '... should