use Test::More;
use strict;
use warnings;
use IO::Socket::INET;
use t::Util;
use Net::Proxy;
# dummy data
my @lines = (
"swa_a_p bang swish bap crunch\n",
"zlonk zok zapeth crunch_eth crraack\n",
"glipp zwapp urkkk cr_r_a_a_ck glurpp\n",
"zzzzzwap thwapp zgruppp awk eee_yow\n",
"ker_plop spla_a_t swoosh cr_r_a_a_ck bang_eth pam uggh\n",
"AEGEAN_NUMBER_NINETY MATHEMATICAL_SANS_SERIF_ITALIC_SMALL_Y\n",
"YI_SYLLABLE_SHUX ARABIC_LIGATURE_THEH_WITH_REH_FINAL_FORM\n",
"TAG_PLUS_SIGN CYPRIOT_SYLLABLE_RE\n",
"TAG_LATIN_CAPITAL_LETTER_S YI_SYLLABLE_QYRX\n",
"MATHEMATICAL_DOUBLE_STRUCK_CAPITAL_U HALFWIDTH_HANGUL_LETTER_YEO\n",
"linguine lasagne_ricce chiocciole\n",
"fusilli_tricolore sedani_corti galla_mezzana\n",
"fettucce_ricce maniche chifferi_rigati\n",
"mista lasagne_festonate_a_nidi nidi\n",
"capelvenere parigine lacchene\n",
"occhi_di_passero guanti ditali\n",
);
# compute a seed and show it
init_rand( @ARGV );
# compute random configurations
my @confs = sort { $a->[0] <=> $b->[0] }
map { [ int rand 16, int rand 8 ] } 1 .. 3;
# compute the total number of tests
my $tests = 1 + ( my $first = int rand 8 );
$tests += $_->[1] for @confs;
$tests += 1 + @confs;
# show the config if
if( @ARGV ) {
diag sprintf "%2d %2d", @$_ for ( [ 0, $first ], @confs );
}
plan tests => $tests;
# lock 2 ports
my @ports = find_free_ports(3);
SKIP: {
skip "Not enough available ports", $tests if @ports < 3;
my ($proxy_port, $server_port, $fake_port) = @ports;
my $pid = fork;
SKIP: {
skip "fork failed", $tests if !defined $pid;
if ( $pid == 0 ) {
# the child process runs the proxy
my $proxy = Net::Proxy->new(
{ in => {
type => 'tcp',
host => 'localhost',
port => $proxy_port
},
out => {
type => 'tcp',
host => 'localhost',
port => $server_port
},
}
);
$proxy->register();
# test unregister()
my $fake_proxy = Net::Proxy->new(
{ in => {
type => 'tcp',
host => 'localhost',
port => $fake_port
},
out => {
type => 'tcp',
host => 'localhost',
port => $server_port
},
}
);
$fake_proxy->register();
$fake_proxy->unregister();
Net::Proxy->set_verbosity( $ENV{NET_PROXY_VERBOSITY} || 0 );
Net::Proxy->mainloop( @confs + 1 );
exit;
}
else {
# wait for the proxy to set up
sleep 1;
# start the server
my $listener = listen_on_port($server_port)
or skip "Couldn't start the server: $!", $tests;
# create the first pair
my %pairs;
{
my $pair = (
[ connect_to_port($proxy_port),
scalar $listener->accept(),
$first, 0
]
);
%pairs = ( $pair => $pair );
}
# check the other proxy is not listening
{
my $client = connect_to_port($fake_port);
is( $client, undef, "Second proxy not here: $!" );
}
my $step = my $n = my $count = 0;
while (%pairs || @confs) {
# create a new connection
CONF:
while ( @confs && $confs[0][0] == $step ) {
my $conf = shift @confs;
my $client = connect_to_port($proxy_port)
or do {
diag "Couldn't start the client: $!";
next CONF;
};
my $server = $listener->accept()
or do { diag "Proxy didn't connect: $!"; next CONF; };
my $pair = [ $client, $server, $conf->[1], ++$count ];
$pairs{$pair} = $pair;
}
PAIR:
for my $pair (values %pairs) {
# close the connection if finished
if ( $pair->[2] <= 0 ) {
$pair->[0]->close();
is_closed( $pair->[1],
"other socket of pair $pair->[3]" );
$pair->[1]->close();
delete $pairs{$pair};
next PAIR;
}
# fetch data to send
$n %= @lines;
my $line = $lines[$n];
# randomly swap client/server
@{$pair}[ 0, 1 ] = random_swap(@{$pair}[ 0, 1 ]);
# send data through the connection
print { $pair->[0] } $line;
is( $pair->[1]->getline(),
$line,
"Step $step: line $n sent through pair $pair->[3]" );
$pair->[2]--;
$n++;
}
$step++;
}
}
}
}