use strict; use warnings; use IO::Socket::INET; # return sockets connected to free ports # we can use sockport() to learn the port values # and close() to close the socket just before reopening it sub find_free_ports { my $n = shift; my @socks; for ( 1 .. $n ) { my $sock = listen_on_port(0); if ($sock) { push @socks, $sock; } } my @ports = map { $_->sockport() } @socks; diag "ports: @ports"; # close the sockets and return the ports $_->close() for @socks; return @ports; } # return a socket connected to port $port on localhost sub connect_to_port { my ($port, %opts) = @_; return IO::Socket::INET->new( PeerAddr => 'localhost', PeerPort => $port, Proto => 'tcp', %opts ); } # return a socket listening on $port on localhost sub listen_on_port { my ($port) = @_; return IO::Socket::INET->new( Listen => 1, LocalAddr => 'localhost', LocalPort => $port, Proto => 'tcp', ); } # compute a seed and show it use POSIX qw( INT_MAX ); sub init_rand { my $seed = @_ ? $_[0] : int rand INT_MAX; diag "Random seed $seed"; srand $seed; } # randomly exchange (or not) a pair sub random_swap { my ( $first, $second ) = @_; return rand > 0.5 ? ( $first, $second ) : ( $second, $first ); } # skip but fail # extends Test::More use Test::Builder; sub skip_fail { my ($why, $how_many) = @_; my $Test = Test::Builder->new(); for( 1 .. $how_many ) { $Test->ok( 0, $why ); } no warnings; last SKIP; } use IO::Select; use Test::More; sub is_closed { my ($sock, $name) = @_; $name ||= "$sock"; my $select = IO::Select->new( $sock ); my @read = $select->can_read(); if( @read ) { my $buf; my $read = $read[0]->sysread( $buf, 4096 ); is( $read, 0, "$name closed" ); } } 1;