This is *not* being sent to p5p _yet_, because I did something either brilliantly
clever or fiendishly stupid to get good coverage.  (It's hard to tell the
difference.)

Relying on reliable networking is pretty unportable, and it's really hard to
get useful test information that way.  I coded up some mock objects for
IO::Socket and IO::Select that made this test much easier.

I've been thinking of using them for other Net::* modules -- if they can be
generalized a little more, our lives will be much easier.  I'd like some
feedback on the approach.

If it's a stupid idea, that's cool.  If it's in the wrong place, that's fine.
If there's a better way to do it, I'm all ears.

Someone has to get this done, though, and if doing things the Max Power way
(wrong, but faster and with more yelling) shakes out better ideas, I'll rush in
where fools fear to tread.

HELP!,
-- c

--- ~MANIFEST   Thu Oct 18 00:54:07 2001
+++ MANIFEST    Thu Oct 18 00:55:15 2001
@@ -1100,7 +1100,8 @@
 lib/Net/t/nntp.t               libnet
 lib/Net/t/require.t            libnet
 lib/Net/t/smtp.t               libnet
-lib/Net/Time.pm                        libnet
+lib/Net/Time.pm                        Get the time from a remote machine
+lib/Net/Time.t                 See if Net::Time works
 lib/newgetopt.pl               A perl library supporting long option parsing
 lib/NEXT.pm                    Pseudo-class NEXT for method redispatch
 lib/NEXT/Changes               NEXT
--- /dev/null   Thu Aug 30 03:54:37 2001
+++ lib/Net/Time.t      Fri Oct 12 12:59:29 2001
@@ -0,0 +1,46 @@
+#!./perl -w
+
+BEGIN {
+       chdir 't' if -d 't';
+       @INC = '../lib';
+}
+
+use Net::t::Mock;
+
+use Test::More 'no_plan';
+
+use_ok( 'Net::Time' );
+
+# force the socket to fail
+make_fail('IO::Socket::INET', 'new');
+is( Net::Time::_socket('foo', 1, 'bar', 'baz'), undef, 
+       '_socket() should fail if Socket creation fails' );
+
+# if socket is created with protocol UDP (default), it will send a newline
+my $sock = Net::Time::_socket('foo', 2, 'bar'); 
+isa_ok( $sock, 'IO::Socket::INET' );
+is( $sock->{sent}, "\n", 'should send \n with UDP protocol set' );
+is( $sock->{timeout}, 120, 'timeout should default to 120' );
+
+# now try it with a custom timeout and a different protocol
+$sock = Net::Time::_socket('foo', 3, 'bar', 'tcp', 11);
+isa_ok( $sock, 'IO::Socket::INET' );
+is( $sock->{sent}, undef, '_socket() should send nothing unless UDP protocol' );
+is( $sock->{PeerAddr}, 'bar', '_socket() should set PeerAddr in socket' );
+is( $sock->{timeout}, 11, '_socket() should respect custom timeout value' );
+
+# inet_daytime
+# check for correct args (daytime, 13)
+IO::Socket::INET::set_message('z');
+is( Net::Time::inet_daytime('bob'), 'z', 'inet_daytime() should receive data' );
+
+# magic numbers defined in Net::Time
+my $offset = $^O eq 'MacOS' ?
+       (4 * 31536000) : (70 * 31536000 + 17 * 86400);
+
+# check for correct args (time, 13)
+# pretend it is only six seconds since the offset, create a fake message
+# inet_time
+IO::Socket::INET::set_message(pack("N", $offset + 6));
+is( Net::Time::inet_time('foo'), 6, 
+       'inet_time() should calculate time since offset for time()' );
--- /dev/null   Thu Aug 30 03:54:37 2001
+++ lib/Net/t/Mock.pm   Fri Oct 12 12:53:59 2001
@@ -0,0 +1,80 @@
+package Net::t::Mock;
+
+my %fail;
+
+sub import {
+       my $pkg = caller;
+       *{ $pkg . '::make_fail' } = sub {
+               my ($pack, $func, $num) = @_;
+               $num = 1 unless defined $num;
+
+               $fail{$pack}{$func} = $num;
+       };
+}
+
+package IO::Socket::INET;
+
+$INC{'IO/Socket/INET.pm'} = 1;
+
+$fail{'IO::Socket::INET'} = {
+       new             => 0,
+       send    => 0,
+};
+
+sub new {
+       my $class = shift;
+       return if $fail{$class}{new} and $fail{$class}{new}--;
+       bless( { @_ }, $class );
+}
+
+sub send {
+       my $self = shift;
+       my $class = ref($self);
+       return if $fail{$class}{send} and $fail{$class}{send}--;
+       $self->{sent} .= shift;
+}
+
+my $msg;
+sub set_message {
+       if (ref($_[0])) {
+               $self->{msg} = $_[1];
+       } else {
+               $msg = shift;
+       }
+}
+
+sub do_recv (\$$$) {
+       my ($buf, $len, $msg) = @_;
+       $$buf .= substr($msg, 0, $len, '');
+}
+
+sub recv {
+       my ($self, $buf, $length, $flags) = @_;
+       my $message = exists $self->{msg} ?
+               $self->{msg} : $msg;
+
+       if (defined($message)) {
+               do_recv($_[1], $length, $message);
+       }
+       1;
+}
+
+package IO::Select;
+
+$INC{'IO/Select.pm'} = 1;
+
+sub new {
+       my $class = shift;
+       return if defined $fail{$class}{new} and $fail{$class}{new}--;
+       bless({sock => shift}, $class);
+}
+
+sub can_read {
+       my ($self, $timeout) = @_;
+       my $class = ref($self);
+       return if defined $fail{$class}{can_read} and $fail{class}{can_read}--;
+       $self->{sock}{timeout} = $timeout;
+       1;
+}
+
+1;

Reply via email to