The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
#!/usr/bin/env perl
# vim: ts=2 sw=2 expandtab

# Something in the request queue is discarding responses.
# Reported in https://rt.cpan.org/Ticket/Display.html?id=72055
#
# Losing a number of pings in the initial phase occurs when special
# conditions are meet:
#
# * Pings are sent to the same host.
# * Parallelism is 2 or more.
# * Al least 2 ping events are created in a row (initial pings).
#
# The number of lost pings: min( Parallelism, initial pings ) - 1.
#
# Correct behavior is for 1 response to be received, and the remaining
# N-1 requests to be forcibly timed out by subsequent duplicate
# requests.

use strict;
use warnings;

BEGIN {
  $| = 1;
  if ($> and ($^O ne 'VMS')) {
    print "1..0 # skipped: ICMP ping requires root privilege\n";
    exit 0;
  }
};

use Test::More tests => 2;

use POE qw( Component::Client::Ping );

POE::Component::Client::Ping->spawn(Parallelism => 10, OneReply => 1);

POE::Session->create(
  inline_states => {
    _start => sub {
      $_[HEAP]{got_answer} = $_[HEAP]{got_timeout} = $_[HEAP]{expected} = 0;

      # It's bad technique to send all the requets at once, but we're
      # doing this to expose a bug in the module's queuing logic.

      my @hosts = ( ('127.0.0.1') x 5 );
      foreach (@hosts) {
        ++$_[HEAP]{expected};
        $_[KERNEL]->post('pinger', 'ping', 'pong', $_);
      }
    },

    _stop => sub {
      is(
        $_[HEAP]{got_timeout}, $_[HEAP]{expected} - 1,
        "got the right number of timeouts"
      );
      is(
        $_[HEAP]{got_answer}, 1,
        "got the right number of answers"
      );
    },

    pong => sub {
      if (defined $_[ARG1]->[0]) {
        ++$_[HEAP]->{got_answer};
      }
      else {
        ++$_[HEAP]->{got_timeout};
      }
    },
  },
);

POE::Kernel->run;