#!/usr/bin/perl use v5.14; use warnings; use Test::More; use Time::HiRes qw(); # Empty import, just there to let IO::Async and Net::Async::IRC use it use IO::Async::Test; use IO::Async::OS; use IO::Async::Loop; use IO::Async::Stream; use Net::Async::IRC; my $CRLF = "\x0d\x0a"; # because \r\n isn't portable my $loop = IO::Async::Loop->new(); testing_loop( $loop ); my ( $S1, $S2 ) = IO::Async::OS->socketpair() or die "Cannot create socket pair - $!"; my $lag; my $pingout; my $irc = Net::Async::IRC->new( handle => $S1, on_message => sub { "IGNORE" }, pingtime => 2, pongtime => 1, on_pong_reply => sub { $lag = $_[1] }, on_ping_timeout => sub { $pingout = 1 }, ); $loop->add( $irc ); # This is all tricky timing-related code. Pay attention # First [the server] will send three messages, separated by 1sec, and assert # that the client didn't send a PING my $serverstream = ""; my $msgcount = 0; sub tick { $msgcount++; $S2->syswrite( "HELLO client$CRLF" ); $loop->enqueue_timer( delay => 1, code => \&tick ) if $msgcount < 3; } tick(); wait_for_stream { $msgcount == 3 } $S2 => $serverstream; is( $serverstream, "", 'client quiet after server noise' ); # Now [the server] will be quiet and assert that the client sends a PING wait_for_stream { $serverstream =~ m/$CRLF/ } $S2 => $serverstream; like( $serverstream, qr/^PING .*$CRLF$/, 'client sent PING after server idle' ); # Now lets be a good server and reply to the PING my ( $pingarg ) = $serverstream =~ m/^PING (.*)$CRLF$/; $S2->syswrite( ":irc.example.com PONG $pingarg$CRLF" ); undef $lag; wait_for { defined $lag }; ok( $lag >= 0 && $lag <= 1, 'client acknowledges PONG reply' ); # Now [the server] won't reply to a PING at all, and hope for an event to note # that it failed wait_for { defined $pingout }; ok( $pingout, 'client reports PING timeout' ); done_testing;