1898184e3Ssthenuse strict;
2898184e3Ssthen
3b39c5158SmillertBEGIN {
4*f2a19305Safresh1  if ($ENV{NO_NETWORK_TESTING} ||
5*f2a19305Safresh1      ($ENV{PERL_CORE} && !$ENV{PERL_TEST_Net_Ping})) {
6b39c5158Smillert    print "1..0 # Skip: network dependent test\n";
7b39c5158Smillert    exit;
8b39c5158Smillert  }
9b39c5158Smillert  unless (eval "require Socket") {
10b39c5158Smillert    print "1..0 \# Skip: no Socket\n";
11b39c5158Smillert    exit;
12b39c5158Smillert  }
13b39c5158Smillert  unless (getservbyname('echo', 'tcp')) {
14b39c5158Smillert    print "1..0 \# Skip: no echo port\n";
15b39c5158Smillert    exit;
16b39c5158Smillert  }
17b39c5158Smillert  unless (getservbyname('http', 'tcp')) {
18b39c5158Smillert    print "1..0 \# Skip: no http port\n";
19b39c5158Smillert    exit;
20b39c5158Smillert  }
21b39c5158Smillert}
22b39c5158Smillert
23b39c5158Smillert# Remote network test using syn protocol.
24b39c5158Smillert#
25b39c5158Smillert# NOTE:
26b39c5158Smillert#   Network connectivity will be required for all tests to pass.
27b39c5158Smillert#   Firewalls may also cause some tests to fail, so test it
28b39c5158Smillert#   on a clear network.  If you know you do not have a direct
29b39c5158Smillert#   connection to remote networks, but you still want the tests
30b39c5158Smillert#   to pass, use the following:
31b39c5158Smillert#
32*f2a19305Safresh1# $ NO_NETWORK_TESTING=1 make test
33b39c5158Smillert
34f3efcd01Safresh1# Hopefully this is never a routeable host
35*f2a19305Safresh1my $fail_ip = $ENV{NET_PING_FAIL_IP} || "192.0.2.0";
36f3efcd01Safresh1
37b39c5158Smillert# Try a few remote servers
385759b3d2Safresh1my %webs = (
39f3efcd01Safresh1  $fail_ip => 0,
40b39c5158Smillert
41b39c5158Smillert  # Hopefully all these web ports are open
42b39c5158Smillert  "yahoo.com." => 1,
43b39c5158Smillert  "www.yahoo.com." => 1,
44b39c5158Smillert  "www.about.com." => 1,
45b39c5158Smillert  "www.microsoft.com." => 1,
46898184e3Ssthen);
47b39c5158Smillert
485759b3d2Safresh1use Test::More;
49f3efcd01Safresh1plan tests => 4 + 2 * keys %webs;
50b39c5158Smillert
515759b3d2Safresh1use_ok('Net::Ping');
52b39c5158Smillert
53b39c5158Smillertmy $can_alarm = eval {alarm 0; 1;};
54b39c5158Smillert
55b39c5158Smillertsub Alarm {
56b39c5158Smillert  alarm(shift) if $can_alarm;
57b39c5158Smillert}
58b39c5158Smillert
59b39c5158SmillertAlarm(50);
60b39c5158Smillert$SIG{ALRM} = sub {
61898184e3Ssthen  fail('Alarm timed out');
62b39c5158Smillert  die "TIMED OUT!";
63b39c5158Smillert};
64b39c5158Smillert
65b39c5158Smillertmy $p = new Net::Ping "syn", 10;
66b39c5158Smillert
67898184e3Ssthenisa_ok($p, 'Net::Ping', 'new() worked');
68b39c5158Smillert
69b39c5158Smillert# Change to use the more common web port.
70b39c5158Smillert# (Make sure getservbyname works in scalar context.)
71898184e3Ssthencmp_ok(($p->{port_num} = getservbyname("http", "tcp")), '>', 0, 'valid port');
72b39c5158Smillert
73f3efcd01Safresh1# message_type can't be used
74f3efcd01Safresh1eval {
75f3efcd01Safresh1  $p->message_type();
76f3efcd01Safresh1};
77f3efcd01Safresh1like($@, qr/message type only supported on 'icmp' protocol/, "message_type() API only concern 'icmp' protocol");
78f3efcd01Safresh1
795759b3d2Safresh1# check if network is up
805759b3d2Safresh1eval { $p->ping('www.google.com.'); };
815759b3d2Safresh1if ($@ =~ /getaddrinfo.*failed/) {
825759b3d2Safresh1  ok(1, "skip $@");
835759b3d2Safresh1  ok(1, "skip") for 0..12;
845759b3d2Safresh1  exit;
855759b3d2Safresh1}
86898184e3Ssthenforeach my $host (keys %webs) {
87b39c5158Smillert  # ping() does dns resolution and
88b39c5158Smillert  # only sends the SYN at this point
89b39c5158Smillert  Alarm(50); # (Plenty for a DNS lookup)
9091f110e0Safresh1  is($p->ping($host), 1, "Can reach $host [" . ($p->{bad}->{$host} || "") . "]");
91b39c5158Smillert}
92b39c5158Smillert
935759b3d2Safresh1my $failed;
94b39c5158SmillertAlarm(20);
95b39c5158Smillertwhile (my $host = $p->ack()) {
965759b3d2Safresh1  next if $host eq 'www.google.com.';
975759b3d2Safresh1  $failed += !is($webs{$host}, 1, "supposed to be up: http://$host/");
98898184e3Ssthen  delete $webs{$host};
99b39c5158Smillert}
100b39c5158Smillert
101b39c5158SmillertAlarm(0);
102898184e3Ssthenforeach my $host (keys %webs) {
1035759b3d2Safresh1  $failed += !is($webs{$host}, 0,
1045759b3d2Safresh1                "supposed to be down: http://$host/ [" . ($p->{bad}->{$host} || "") . "]");
1055759b3d2Safresh1}
1065759b3d2Safresh1
1075759b3d2Safresh1if ($failed) {
1085759b3d2Safresh1  diag ("NOTE: ",
1095759b3d2Safresh1        "Network connectivity will be required for all tests to pass.\n",
1105759b3d2Safresh1        "Firewalls may also cause some tests to fail, so test it ",
1115759b3d2Safresh1        "on a clear network.");
112b39c5158Smillert}
113