mirror of https://github.com/BOINC/boinc.git
testing upload and connection failures
svn path=/trunk/boinc/; revision=1510
This commit is contained in:
parent
23d43298b0
commit
9d73195870
|
@ -4689,3 +4689,14 @@ Karl 2003/06/16
|
|||
|
||||
_autosetup
|
||||
configure.ac
|
||||
|
||||
Karl 2003/06/16
|
||||
Testing upload and connection failures (work in progress)
|
||||
|
||||
test.inc
|
||||
test_uc.inc
|
||||
test_uc.php
|
||||
test_masterurl_failure.php
|
||||
test_upload_resume.php
|
||||
test_upload_backoff.php
|
||||
testproxy
|
||||
|
|
|
@ -108,11 +108,20 @@ function verbose_XPassThru($cmd, $failok=0)
|
|||
return XPassThru($cmd, $failok);
|
||||
}
|
||||
|
||||
function proxerize($s, $t)
|
||||
{
|
||||
if ($t) {
|
||||
return preg_replace(",http://[^/]*/,", "http://localhost:8080/", $s);
|
||||
} else {
|
||||
return $s;
|
||||
}
|
||||
}
|
||||
|
||||
define("KEY_DIR" , get_env_var("BOINC_KEY_DIR"));
|
||||
define("SHMEM_KEY" , get_env_var("BOINC_SHMEM_KEY"));
|
||||
define("PROJECTS_DIR" , get_env_var("BOINC_PROJECTS_DIR"));
|
||||
define("CGI_URL" , get_env_var("BOINC_CGI_URL"));
|
||||
define("HTML_URL" , get_env_var("BOINC_HTML_URL"));
|
||||
define("CGI_URL" , proxerize(get_env_var("BOINC_CGI_URL"), $use_proxy_cgi));
|
||||
define("HTML_URL" , proxerize(get_env_var("BOINC_HTML_URL"), $use_proxy_html));
|
||||
define("USER_NAME" , get_env_var("BOINC_USER_NAME", get_env_var("USER","")));
|
||||
define("CGI_DIR" , get_env_var("BOINC_CGI_DIR"));
|
||||
define("HTML_DIR" , get_env_var("BOINC_HTML_DIR"));
|
||||
|
@ -927,6 +936,7 @@ class Host {
|
|||
// get_new_boincpid() must be called and kill() must be called on it.
|
||||
//
|
||||
function run_asynch($args) {
|
||||
// TODO: just use shell & to background?
|
||||
$pid = pcntl_fork();
|
||||
if ($pid == -1) {
|
||||
return -1;
|
||||
|
@ -935,9 +945,11 @@ class Host {
|
|||
} else { //we are the child
|
||||
verbose_echo(1, "Running core client asynch");
|
||||
$source_dir = SRC_DIR;
|
||||
$platform = PLATFORM;
|
||||
$exec_name = CLIENT_BIN_FILENAME;
|
||||
XPassThru("cd $this->host_dir; $source_dir/client/$exec_name $args > client.out");
|
||||
assert($source_dir && 1);
|
||||
assert($exec_name && 1);
|
||||
assert($this->host_dir && 1);
|
||||
verbose_XPassThru("cd $this->host_dir; $source_dir/client/$exec_name $args > client.out");
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
@ -959,7 +971,10 @@ class Host {
|
|||
verbose_echo(1, "Running core client");
|
||||
$source_dir = SRC_DIR;
|
||||
$exec_name = CLIENT_BIN_FILENAME;
|
||||
XPassThru("cd $this->host_dir; $source_dir/client/$exec_name $args > client.out", $ret);
|
||||
assert($source_dir && 1);
|
||||
assert($exec_name && 1);
|
||||
assert($this->host_dir && 1);
|
||||
verbose_XPassThru("cd $this->host_dir; $source_dir/client/$exec_name $args > client.out", $ret);
|
||||
assert ($ret == 0);
|
||||
}
|
||||
|
||||
|
@ -1070,6 +1085,11 @@ class Work {
|
|||
}
|
||||
}
|
||||
|
||||
function start_proxy($code)
|
||||
{
|
||||
verbose_XPassThru("./testproxy 8080 localhost:80 '$code' 2>/dev/null &");
|
||||
}
|
||||
|
||||
function test_msg($msg)
|
||||
{
|
||||
echo "-- Testing " . $msg . ' ' . str_repeat('-', 78 - strlen($msg)-12) . "\n";
|
||||
|
|
|
@ -1,56 +1,22 @@
|
|||
#! /usr/local/bin/php
|
||||
<?php
|
||||
//This tests the exponential backoff mechanism on the client in case of master IURL failures
|
||||
//This test is not automated. It has to be run, and then client.out (in the host directory) must be looked at to examine wether everything is working correctly.
|
||||
include_once("test.inc");
|
||||
#!/usr/local/bin/php -q
|
||||
<?php {
|
||||
// $Id$
|
||||
|
||||
$project = new Project;
|
||||
$user = new User();
|
||||
$host = new Host($user);
|
||||
$use_proxy_html = 1;
|
||||
|
||||
$app = new App("upper_case");
|
||||
$app_version = new App_Version($app);
|
||||
include_once("test_uc.inc");
|
||||
test_msg("master url failure");
|
||||
|
||||
// the following is optional (makes client web download possible)
|
||||
$core_app = new App("core client");
|
||||
$core_app_version = new App_Version($core_app);
|
||||
$project->add_app($core_app);
|
||||
$project->add_app_version($core_app_version);
|
||||
$project = new ProjectUC;
|
||||
|
||||
$project->add_user($user);
|
||||
$project->add_app($app);
|
||||
$project->add_app_version($app_version);
|
||||
start_proxy('exit 1 if $nconnections < 4; if_done_kill(); if_done_ping();');
|
||||
|
||||
$project->install(); // must install projects before adding to hosts
|
||||
// TODO: verify it took ??? seconds
|
||||
|
||||
$host->log_flags = "log_flags.xml";
|
||||
$host->add_project($project);
|
||||
$host->install();
|
||||
// TODO: time out after ??? seconds and fail this test
|
||||
|
||||
echo "adding work\n";
|
||||
$project->start_servers_and_host();
|
||||
$project->validate_all_and_stop();
|
||||
|
||||
$work = new Work($app);
|
||||
$work->wu_template = "uc_wu";
|
||||
$work->result_template = "uc_result";
|
||||
$work->redundancy = 2;
|
||||
$work->delay_bound = 10;
|
||||
array_push($work->input_files, "input");
|
||||
$work->install($project);
|
||||
|
||||
$project->start_feeder();
|
||||
$project->delete_masterindex();
|
||||
$pid = $host->run_asynch("-exit_when_idle");
|
||||
echo "sleeping for 100 seconds\n";
|
||||
sleep(100);
|
||||
$project->reestablish_masterindex();
|
||||
$status = 0;
|
||||
pcntl_waitpid($pid,$status,0);
|
||||
$project->stop();
|
||||
|
||||
$result->server_state = RESULT_SERVER_STATE_OVER;
|
||||
$result->stderr_out = "APP: upper_case: starting, argc 1";
|
||||
$result->exit_status = 0;
|
||||
$project->check_results(2, $result);
|
||||
$project->compare_file("uc_wu_0_0", "uc_correct_output");
|
||||
$project->compare_file("uc_wu_1_0", "uc_correct_output");
|
||||
?>
|
||||
test_done();
|
||||
} ?>
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
<?php {
|
||||
// $Id$
|
||||
|
||||
include_once("test.inc");
|
||||
|
||||
class ProjectUC extends Project
|
||||
{
|
||||
var $work;
|
||||
var $host;
|
||||
var $user;
|
||||
|
||||
function ProjectUC() {
|
||||
$this->Project();
|
||||
$this->add_core_and_version();
|
||||
$this->add_app_and_version("upper_case");
|
||||
|
||||
$this->user = new User();
|
||||
$this->user->project_prefs = "<project_specific>\nfoobar\n</project_specific>\n";
|
||||
$this->user->global_prefs = "<venue name=\"home\">\n".
|
||||
"<work_buf_min_days>0</work_buf_min_days>\n".
|
||||
"<work_buf_max_days>2</work_buf_max_days>\n".
|
||||
"<disk_interval>1</disk_interval>\n".
|
||||
"<run_on_batteries/>\n".
|
||||
"<max_bytes_sec_down>400000</max_bytes_sec_down>\n".
|
||||
"</venue>\n";
|
||||
|
||||
$this->add_user($this->user);
|
||||
$this->install(); // must install projects before adding to hosts
|
||||
$this->install_feeder();
|
||||
|
||||
$this->host = new Host();
|
||||
$this->host->add_user($this->user, $this);
|
||||
$this->host->install();
|
||||
|
||||
$this->work = new Work();
|
||||
$this->work->wu_template = "uc_wu";
|
||||
$this->work->result_template = "uc_result";
|
||||
$this->work->redundancy = 2;
|
||||
$this->work->delay_bound = 10;
|
||||
// Say that 1 WU takes 1 day on a ref comp
|
||||
$this->work->rsc_fpops = 86400*1e9/2;
|
||||
$this->work->rsc_iops = 86400*1e9/2;
|
||||
$this->work->rsc_disk = 10e8;
|
||||
array_push($this->work->input_files, "input");
|
||||
$this->work->install($this);
|
||||
}
|
||||
|
||||
function start_servers_and_host()
|
||||
{
|
||||
$this->start_servers();
|
||||
$this->host->run("-exit_when_idle -skip_cpu_benchmarks");
|
||||
}
|
||||
|
||||
function validate_all_and_stop()
|
||||
{
|
||||
$this->validate($this->work->redundancy);
|
||||
$result->server_state = RESULT_SERVER_STATE_OVER;
|
||||
$result->stderr_out = "APP: upper_case: starting, argc 1
|
||||
APP: upper_case: argv[0] is upper_case
|
||||
APP: upper_case ending, wrote ";
|
||||
$result->exit_status = 0;
|
||||
$this->check_results(2, $result);
|
||||
$this->compare_file("uc_wu_0_0", "uc_correct_output");
|
||||
$this->compare_file("uc_wu_1_0", "uc_correct_output");
|
||||
|
||||
$this->assimilate();
|
||||
$this->file_delete();
|
||||
|
||||
$this->check_server_deleted("download/input");
|
||||
$this->check_server_deleted("upload/uc_wu_0_0");
|
||||
$this->check_server_deleted("upload/uc_wu_1_0");
|
||||
$this->stop();
|
||||
}
|
||||
}
|
||||
} ?>
|
|
@ -6,64 +6,12 @@
|
|||
// Also whether stderr output is reported correctly
|
||||
// Also tests if water levels are working correctly
|
||||
|
||||
include_once("test.inc");
|
||||
|
||||
include_once("test_uc.inc");
|
||||
test_msg("standard upper_case application");
|
||||
|
||||
$project = new Project;
|
||||
$project->add_core_and_version();
|
||||
$project->add_app_and_version("upper_case");
|
||||
|
||||
$user = new User();
|
||||
$user->project_prefs = "<project_specific>\nfoobar\n</project_specific>\n";
|
||||
$user->global_prefs = "<venue name=\"home\">\n".
|
||||
"<work_buf_min_days>0</work_buf_min_days>\n".
|
||||
"<work_buf_max_days>2</work_buf_max_days>\n".
|
||||
"<disk_interval>1</disk_interval>\n".
|
||||
"<run_on_batteries/>\n".
|
||||
"<max_bytes_sec_down>400000</max_bytes_sec_down>\n".
|
||||
"</venue>\n";
|
||||
|
||||
$project->add_user($user);
|
||||
$project->install(); // must install projects before adding to hosts
|
||||
$project->install_feeder();
|
||||
|
||||
$host = new Host();
|
||||
$host->add_user($user, $project);
|
||||
$host->install();
|
||||
|
||||
$work = new Work();
|
||||
$work->wu_template = "uc_wu";
|
||||
$work->result_template = "uc_result";
|
||||
$work->redundancy = 2;
|
||||
$work->delay_bound = 10;
|
||||
// Say that 1 WU takes 1 day on a ref comp
|
||||
$work->rsc_fpops = 86400*1e9/2;
|
||||
$work->rsc_iops = 86400*1e9/2;
|
||||
$work->rsc_disk = 10e8;
|
||||
array_push($work->input_files, "input");
|
||||
$work->install($project);
|
||||
|
||||
$project->start_servers();
|
||||
$host->run("-exit_when_idle -skip_cpu_benchmarks");
|
||||
|
||||
$project->validate(2);
|
||||
$result->server_state = RESULT_SERVER_STATE_OVER;
|
||||
$result->stderr_out = "APP: upper_case: starting, argc 1
|
||||
APP: upper_case: argv[0] is upper_case
|
||||
APP: upper_case ending, wrote ";
|
||||
$result->exit_status = 0;
|
||||
$project->check_results(2, $result);
|
||||
$project->compare_file("uc_wu_0_0", "uc_correct_output");
|
||||
$project->compare_file("uc_wu_1_0", "uc_correct_output");
|
||||
|
||||
$project->assimilate();
|
||||
$project->file_delete();
|
||||
|
||||
$project->check_server_deleted("download/input");
|
||||
$project->check_server_deleted("upload/uc_wu_0_0");
|
||||
$project->check_server_deleted("upload/uc_wu_1_0");
|
||||
$project->stop();
|
||||
$project = new ProjectUC;
|
||||
$project->start_servers_and_host();
|
||||
$project->validate_all_and_stop();
|
||||
|
||||
test_done();
|
||||
} ?>
|
||||
|
|
|
@ -1,58 +1,23 @@
|
|||
#! /usr/local/bin/php
|
||||
<?php
|
||||
//This tests the exponential backoff mechanism on the client in case of downloadURLs going down
|
||||
//This test is not automated. It has to be run, and then client.out (in the host directory) must be looked at to examine wether everything is working correctly.
|
||||
include_once("test.inc");
|
||||
#!/usr/local/bin/php -q
|
||||
<?php {
|
||||
// $Id$
|
||||
|
||||
$project = new Project;
|
||||
$user = new User();
|
||||
$host = new Host($user);
|
||||
// This tests whether upload resuming works correctly.
|
||||
|
||||
$app = new App("upper_case");
|
||||
$app_version = new App_Version($app);
|
||||
$use_proxy_cgi = 1;
|
||||
|
||||
// the following is optional (makes client web download possible)
|
||||
$core_app = new App("core client");
|
||||
$core_app_version = new App_Version($core_app);
|
||||
$project->add_app($core_app);
|
||||
$project->add_app_version($core_app_version);
|
||||
include_once("test_uc.inc");
|
||||
test_msg("upload backoff");
|
||||
|
||||
$project->add_user($user);
|
||||
$project->add_app($app);
|
||||
$project->add_app_version($app_version);
|
||||
$project = new ProjectUC;
|
||||
|
||||
$project->install(); // must install projects before adding to hosts
|
||||
// TODO
|
||||
// start_proxy('exit 1 if ($nconnections < 4); if_done_kill(); if_done_ping();');
|
||||
|
||||
$host->log_flags = "log_flags.xml";
|
||||
$host->add_project($project);
|
||||
$host->install();
|
||||
// $pid = $host->run_asynch("-exit_when_idle");
|
||||
|
||||
echo "adding work\n";
|
||||
$project->start_servers_and_host();
|
||||
$project->validate_all_and_stop();
|
||||
|
||||
$work = new Work($app);
|
||||
$work->wu_template = "uc_wu";
|
||||
$work->result_template = "uc_result";
|
||||
$work->redundancy = 2;
|
||||
$work->delay_bound = 10;
|
||||
array_push($work->input_files, "input");
|
||||
$work->install($project);
|
||||
|
||||
$project->start_feeder();
|
||||
$project->remove_file_upload_handler();
|
||||
$pid = $host->run_asynch("-exit_when_idle");
|
||||
|
||||
echo "sleeping 20 secs\n";
|
||||
sleep(20);
|
||||
$project->reinstall_file_upload_handler(null);
|
||||
$status = 0;
|
||||
//wait until the host has stopped running
|
||||
pcntl_waitpid($pid, $status,0);
|
||||
$project->stop();
|
||||
|
||||
$result->server_state = RESULT_SERVER_STATE_OVER;
|
||||
$result->stderr_out = "APP: upper_case: starting, argc 1";
|
||||
$result->exit_status = 0;
|
||||
$project->check_results(2, $result);
|
||||
$project->compare_file("uc_wu_0_0", "uc_correct_output");
|
||||
$project->compare_file("uc_wu_1_0", "uc_correct_output");
|
||||
?>
|
||||
test_done();
|
||||
} ?>
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
#!/usr/local/bin/php -q
|
||||
<?php {
|
||||
// $Id$
|
||||
|
||||
// This tests whether upload resuming works correctly.
|
||||
|
||||
$use_proxy_cgi = 1;
|
||||
|
||||
include_once("test_uc.inc");
|
||||
test_msg("upload resumes");
|
||||
|
||||
$project = new ProjectUC;
|
||||
|
||||
// TODO
|
||||
// start_proxy('exit 1 if ($nconnections ==1 && $bytes_transferred==ZZZ); if_done_kill(); if_done_ping();');
|
||||
|
||||
$project->start_servers_and_host();
|
||||
$project->validate_all_and_stop();
|
||||
|
||||
test_done();
|
||||
} ?>
|
|
@ -0,0 +1,224 @@
|
|||
#!/usr/bin/env perl
|
||||
|
||||
# -T
|
||||
|
||||
# $Id$
|
||||
|
||||
# The contents of this file are subject to the Mozilla Public License
|
||||
# Version 1.0 (the "License"); you may not use this file except in
|
||||
# compliance with the License. You may obtain a copy of the License at
|
||||
# http:#www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS"
|
||||
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing rights and limitations
|
||||
# under the License.
|
||||
#
|
||||
# The Original Code is the Berkeley Open Infrastructure for Network Computing.
|
||||
#
|
||||
# The Initial Developer of the Original Code is the SETI@home project.
|
||||
# Portions created by the SETI@home project are Copyright (C) 2002, 2003
|
||||
# University of California at Berkeley. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
|
||||
# testproxy - proxy a TCP/IP connection with configurable mid-way
|
||||
# disconnections, for simulating internet transfer failures
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Carp;
|
||||
use IO::Socket::INET;
|
||||
|
||||
my $listen_port = shift;
|
||||
my $target_server = shift;
|
||||
my $testcode = join(' ', @ARGV);
|
||||
|
||||
if (!$listen_port || !$target_server) {
|
||||
print STDERR <<HELP;
|
||||
syntax: $0 <listen_port> <target_server:port> CODE...
|
||||
|
||||
CODE is evaluated every 128 bytes transferred from server to client.
|
||||
Some variables you can access/modify:
|
||||
\$target, \$client : perl IO::Handle::INET objects
|
||||
\$nconnections : number of connections so far
|
||||
\$chars, \$nchars : characters & length about to send to client.
|
||||
\$bytes_transferred : characters already sent to client
|
||||
\$done, \$success : finished transfer; successful transfer
|
||||
|
||||
For more, view the code.
|
||||
|
||||
You can call functions like exit, sleep, \$target\->close, \$target\->print.
|
||||
You should return 1 to indicate success (otherwise testproxy will warn).
|
||||
|
||||
Examples:
|
||||
# fail connections for first 3 connections
|
||||
$0 8080 localhost:80 'exit 1 if \$nconnections < 4; 1'
|
||||
|
||||
# sleep 5 seconds in the middle of transfer, and print "success" if
|
||||
# transfer succeeds; kill the server after the first connection
|
||||
$0 8080 localhost:80 'sleep 5 if \$bytes_transferred == 256;
|
||||
if (\$done) { print "success\\n" if \$success; kill_server; \$success }
|
||||
else { 1 }'
|
||||
|
||||
# equivalent to above:
|
||||
$0 8080 localhost:80 'sleep 5 if \$bytes_transferred == 256;
|
||||
if_done_kill(); if_done_ping();'
|
||||
|
||||
HELP
|
||||
;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if ($target_server !~ /:/) {
|
||||
$target_server .= ':http';
|
||||
}
|
||||
|
||||
my $N = "\015\012";
|
||||
|
||||
sub proxy;
|
||||
sub spawn;
|
||||
sub logmsg { print STDERR "$0 $$: @_ at ", scalar localtime, "\n" }
|
||||
|
||||
my $server = IO::Socket::INET->new(Listen => 5,
|
||||
LocalAddr => inet_ntoa(INADDR_ANY),
|
||||
LocalPort => $listen_port,
|
||||
Proto => 'tcp',
|
||||
ReuseAddr => 1)
|
||||
or die "$0: creating socket on port $listen_port: $!";
|
||||
|
||||
logmsg "server started on port $listen_port proxy to $target_server";
|
||||
|
||||
my $waitedpid = 0;
|
||||
my $paddr;
|
||||
|
||||
my $server_pid = $$;
|
||||
|
||||
use POSIX ":sys_wait_h";
|
||||
sub REAPER {
|
||||
my $child;
|
||||
while (($waitedpid = waitpid(-1,WNOHANG)) > 0) {
|
||||
# logmsg "reaped $waitedpid" . ($? ? " with exit $?" : '');
|
||||
}
|
||||
$SIG{CHLD} = \&REAPER; # loathe sysV
|
||||
}
|
||||
|
||||
$SIG{CHLD} = \&REAPER;
|
||||
|
||||
my $nconnections = 0;
|
||||
|
||||
my $client;
|
||||
|
||||
for ( $waitedpid = 0;
|
||||
($client = $server->accept()) || $waitedpid;
|
||||
$waitedpid = 0)
|
||||
{
|
||||
next if $waitedpid and not $client;
|
||||
die unless $client;
|
||||
my $paddr = $client->peername();
|
||||
my($port,$iaddr) = sockaddr_in($paddr);
|
||||
my $name = gethostbyaddr($iaddr,AF_INET);
|
||||
|
||||
logmsg "connection from $name", "[", inet_ntoa($iaddr), "]:$port";
|
||||
|
||||
++$nconnections;
|
||||
|
||||
spawn \&proxy, $client;
|
||||
}
|
||||
|
||||
sub spawn {
|
||||
my $coderef = shift;
|
||||
|
||||
unless ($coderef && ref($coderef) eq 'CODE') {
|
||||
confess "usage: spawn CODEREF";
|
||||
}
|
||||
|
||||
my $pid;
|
||||
if (!defined($pid = fork)) {
|
||||
logmsg "cannot fork: $!";
|
||||
return;
|
||||
} elsif ($pid) {
|
||||
# logmsg "begat $pid";
|
||||
return; # I'm the parent
|
||||
}
|
||||
# else I'm the child -- go spawn
|
||||
|
||||
exit &$coderef(@_);
|
||||
}
|
||||
|
||||
sub kill_server()
|
||||
{
|
||||
kill "INT", $server_pid;
|
||||
}
|
||||
|
||||
my $done = 0;
|
||||
my $success = 0;
|
||||
|
||||
sub if_done_ping()
|
||||
{
|
||||
if ($done) {
|
||||
if ($success) {
|
||||
print "success\n";
|
||||
} else {
|
||||
print "failed\n";
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
1;
|
||||
}
|
||||
|
||||
sub if_done_kill()
|
||||
{
|
||||
if ($done) {
|
||||
kill_server();
|
||||
}
|
||||
1;
|
||||
}
|
||||
|
||||
sub proxy {
|
||||
my $client = shift or die;
|
||||
|
||||
my $target = IO::Socket::INET->new(PeerAddr => $target_server)
|
||||
or die "$0: couldn't connect to $target_server: $!";
|
||||
|
||||
$client->autoflush(1);
|
||||
$target->autoflush(1);
|
||||
|
||||
# transfer lines from client -> server until we get an empty line
|
||||
|
||||
while (my $line = $client->getline()) {
|
||||
$target->print($line);
|
||||
$line =~ s/[\015\012]+$//;
|
||||
last unless $line;
|
||||
}
|
||||
|
||||
# transfer from server->client
|
||||
my $bytes_transferred = 0;
|
||||
|
||||
# while (my $line = $target->getline()) {
|
||||
# $bytes_transferred += length($line);
|
||||
# print "[$bytes_transferred] $line";
|
||||
# $client->print($line);
|
||||
# }
|
||||
|
||||
$done = 0;
|
||||
$success = 0;
|
||||
my $chars;
|
||||
my $nchars;
|
||||
while ($nchars = $target->read($chars, 128)) {
|
||||
eval $testcode || warn;
|
||||
$bytes_transferred += $nchars;
|
||||
$client->write($chars, $nchars);
|
||||
}
|
||||
|
||||
{
|
||||
$chars = undef; $nchars = 0;
|
||||
$done = 1;
|
||||
$success = $client->connected() && 1;
|
||||
eval $testcode || warn;
|
||||
}
|
||||
|
||||
$target->close();
|
||||
$client->close();
|
||||
}
|
Loading…
Reference in New Issue