mirror of https://github.com/BOINC/boinc.git
fixed client state after file abort bug ; test scripts
svn path=/trunk/boinc/; revision=1600
This commit is contained in:
parent
b780baa4ba
commit
054eb0521a
|
@ -5069,3 +5069,17 @@ Karl 2003/06/25
|
|||
cronjob - complains if anything fails.
|
||||
|
||||
./testbase (new)
|
||||
|
||||
Karl 2003/06/26
|
||||
- fixed bug that caused client state to transition to
|
||||
RESULT_FILES_UPLOADING even when file info(s) had errors; now it stays
|
||||
in RESULT_COMPUTE_DONE.
|
||||
- test makefile should rebuild version.py and boinc_db.py if necessary
|
||||
- test_sanity should make sure proxy setup works
|
||||
- test_masterurl_failure
|
||||
|
||||
test/
|
||||
Makefile.am
|
||||
test_sanity.py
|
||||
boinc.py
|
||||
test_masterurl_failure.py
|
||||
|
|
|
@ -1344,18 +1344,20 @@ bool CLIENT_STATE::update_results() {
|
|||
action = true;
|
||||
}
|
||||
break;
|
||||
case RESULT_FILES_DOWNLOADED:
|
||||
// The transition to COMPUTE_DONE is performed
|
||||
// in app_finished()
|
||||
break;
|
||||
case RESULT_COMPUTE_DONE:
|
||||
// Once the computation has been done, check
|
||||
// that the necessary files have been uploaded
|
||||
// before moving on
|
||||
rp->state = RESULT_FILES_UPLOADING;
|
||||
action = true;
|
||||
break;
|
||||
|
||||
// app_finished() transitions to either RESULT_COMPUTE_DONE or
|
||||
// RESULT_FILES_UPLOADING. RESULT_COMPUTE_DONE is a dead-end state
|
||||
// indicating we had an error at the end of computation.
|
||||
|
||||
// case RESULT_FILES_DOWNLOADED:
|
||||
// break;
|
||||
// case RESULT_COMPUTE_DONE:
|
||||
// rp->state = RESULT_FILES_UPLOADING;
|
||||
// action = true;
|
||||
// break;
|
||||
case RESULT_FILES_UPLOADING:
|
||||
// Once the computation has been done, check that the necessary
|
||||
// files have been uploaded before moving on
|
||||
if (rp->is_upload_done()) {
|
||||
rp->ready_to_ack = true;
|
||||
rp->state = RESULT_FILES_UPLOADED;
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
// 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/
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// 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
|
||||
// University of California at Berkeley. All Rights Reserved.
|
||||
//
|
||||
// Portions created by the SETI@home project are Copyright (C) 2002, 2003
|
||||
// University of California at Berkeley. All Rights Reserved.
|
||||
//
|
||||
// Contributor(s):
|
||||
//
|
||||
|
||||
|
@ -93,40 +93,53 @@ int CLIENT_STATE::app_finished(ACTIVE_TASK& at) {
|
|||
int retval;
|
||||
double size;
|
||||
|
||||
bool had_error = false;
|
||||
|
||||
for (i=0; i<rp->output_files.size(); i++) {
|
||||
fip = rp->output_files[i].file_info;
|
||||
get_pathname(fip, path);
|
||||
retval = file_size(path, size);
|
||||
if (retval) {
|
||||
// an output file is unexpectedly absent.
|
||||
//
|
||||
//
|
||||
fip->status = retval;
|
||||
} else {
|
||||
if (size > fip->max_nbytes) {
|
||||
msg_printf(at.result->project, MSG_INFO, "Output file %s for result %s exceeds size limit.",
|
||||
fip->name, at.result->name);
|
||||
had_error = true;
|
||||
} else if (size > fip->max_nbytes) {
|
||||
// Note: this is only checked when the application finishes. there
|
||||
// is also a check_max_disk_exceeded that is checked while the
|
||||
// application is running.
|
||||
msg_printf(rp->project, MSG_INFO, "Output file %s for result %s exceeds size limit.",
|
||||
fip->name, rp->name);
|
||||
|
||||
fip->delete_file();
|
||||
fip->status = ERR_FILE_TOO_BIG;
|
||||
fip->delete_file();
|
||||
fip->status = ERR_FILE_TOO_BIG;
|
||||
had_error = true;
|
||||
} else {
|
||||
if (!fip->upload_when_present && !fip->sticky) {
|
||||
fip->delete_file(); // sets status to NOT_PRESENT
|
||||
} else {
|
||||
if (!fip->upload_when_present && !fip->sticky) {
|
||||
fip->delete_file(); // sets status to NOT_PRESENT
|
||||
retval = md5_file(path, fip->md5_cksum, fip->nbytes);
|
||||
if (retval) {
|
||||
fip->status = retval;
|
||||
had_error = true;
|
||||
} else {
|
||||
retval = md5_file(path, fip->md5_cksum, fip->nbytes);
|
||||
if (retval) {
|
||||
fip->status = retval;
|
||||
} else {
|
||||
fip->status = FILE_PRESENT;
|
||||
}
|
||||
fip->status = FILE_PRESENT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
at.result->is_active = false;
|
||||
at.result->state = RESULT_COMPUTE_DONE;
|
||||
update_avg_cpu(at.result->project);
|
||||
at.result->project->exp_avg_cpu += at.result->final_cpu_time;
|
||||
rp->is_active = false;
|
||||
if (had_error) {
|
||||
// dead-end state indicating we had an error at end of computation;
|
||||
// do not move to RESULT_FILES_UPLOADING
|
||||
rp->state = RESULT_COMPUTE_DONE;
|
||||
} else {
|
||||
// can now upload files.
|
||||
rp->state = RESULT_FILES_UPLOADING;
|
||||
}
|
||||
update_avg_cpu(rp->project);
|
||||
rp->project->exp_avg_cpu += rp->final_cpu_time;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,8 @@ noinst_SCRIPTS = \
|
|||
|
||||
BUILT_SOURCES = boinc_db.inc boinc_db.py
|
||||
|
||||
$(TESTS): version.py boinc_db.py
|
||||
|
||||
boinc_db.inc: ../db/boinc_db.h
|
||||
./db_def_to_php < ../db/boinc_db.h > boinc_db.inc
|
||||
|
||||
|
|
|
@ -415,6 +415,8 @@ uninstall-am: uninstall-info-am
|
|||
$(LIBRSA):
|
||||
cd $(top_builddir)/RSAEuro/source; ${MAKE} librsaeuro.a
|
||||
|
||||
$(TESTS): version.py boinc_db.py
|
||||
|
||||
boinc_db.inc: ../db/boinc_db.h
|
||||
./db_def_to_php < ../db/boinc_db.h > boinc_db.inc
|
||||
|
||||
|
|
|
@ -66,20 +66,24 @@ def verbose_sleep(msg, wait):
|
|||
verbose_echo(1, msg + ' [sleep ' + ('.'*i).ljust(wait) + ']')
|
||||
time.sleep(1)
|
||||
|
||||
def shell_call(cmd, failok=False):
|
||||
def shell_call(cmd, doexec=False, failok=False):
|
||||
if doexec:
|
||||
os.execl('/bin/sh', 'sh', '-c', cmd)
|
||||
error("Command failed: "+cmd)
|
||||
os._exit(1)
|
||||
if os.system(cmd):
|
||||
error("Command failed: "+cmd, fatal=(not failok))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def verbose_shell_call(cmd, failok=False):
|
||||
def verbose_shell_call(cmd, doexec=False, failok=False):
|
||||
verbose_echo(2, " "+cmd)
|
||||
return shell_call(cmd, failok)
|
||||
return shell_call(cmd, doexec, failok)
|
||||
|
||||
def proxerize(url, t):
|
||||
def proxerize(url, t=True):
|
||||
if t:
|
||||
r = re.compile('http://[^/]*/')
|
||||
return r.sub('http://localhost:080/', url)
|
||||
return r.sub('http://localhost:8080/', url)
|
||||
else:
|
||||
return url
|
||||
|
||||
|
@ -94,8 +98,10 @@ HTML_DIR = get_env_var("BOINC_HTML_DIR")
|
|||
HOSTS_DIR = get_env_var("BOINC_HOSTS_DIR")
|
||||
|
||||
def use_cgi_proxy():
|
||||
global CGI_URL
|
||||
CGI_URL = proxerize(CGI_URL)
|
||||
def use_html_proxy():
|
||||
global HTML_URL
|
||||
HTML_URL = proxerize(HTML_URL)
|
||||
|
||||
def check_exists(file):
|
||||
|
@ -889,23 +895,32 @@ def run_check_all():
|
|||
all_projects.check()
|
||||
# all_projects.stop()
|
||||
|
||||
proxy_pid = 0
|
||||
def start_proxy(code):
|
||||
global proxy_pid
|
||||
pid = os.fork()
|
||||
if not pid:
|
||||
os._exit(verbose_shell_call("./testproxy 8080 localhost:80 '$code' 2>testproxy.log"))
|
||||
|
||||
verbose_sleep("Starting proxy server", 1)
|
||||
proxy_pid = pid
|
||||
# check if child process died
|
||||
(pid,status) = os.waitpid(pid, os.WNOHANG)
|
||||
if pid:
|
||||
fatal_error("testproxy failed")
|
||||
def stop_proxy():
|
||||
global proxy_pid
|
||||
if proxy_pid:
|
||||
os.kill(2, proxy_pid)
|
||||
class Proxy:
|
||||
def __init__(self, code, cgi=0, html=0, start=1):
|
||||
self.pid = 0
|
||||
self.code = code
|
||||
if cgi: use_cgi_proxy()
|
||||
if html: use_html_proxy()
|
||||
if start: self.start()
|
||||
def start(self):
|
||||
self.pid = os.fork()
|
||||
if not self.pid:
|
||||
verbose_shell_call("exec ./testproxy 8080 localhost:80 '%s' 2>testproxy.log"%self.code,
|
||||
doexec=True)
|
||||
verbose_sleep("Starting proxy server", 1)
|
||||
# check if child process died
|
||||
(pid,status) = os.waitpid(self.pid, os.WNOHANG)
|
||||
if pid:
|
||||
fatal_error("testproxy failed")
|
||||
atexit.register(self.stop)
|
||||
def stop(self):
|
||||
verbose_echo(1, "Stopping proxy server")
|
||||
if self.pid:
|
||||
try:
|
||||
os.kill(self.pid, 2)
|
||||
except OSError:
|
||||
verbose_echo(0, "Couldn't kill pid %d" % self.pid)
|
||||
self.pid = 0
|
||||
|
||||
def test_msg(msg):
|
||||
print
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
## $Id$
|
||||
|
||||
from test_uc import *
|
||||
|
||||
if __name__ == '__main__':
|
||||
test_msg("scheduler exponential backoff (master url failure)")
|
||||
proxy = Proxy('exit 1 if $nconnections < 4; if_done_kill(); if_done_ping();',
|
||||
html=1)
|
||||
ProjectUC()
|
||||
run_check_all()
|
||||
|
||||
## TODO: verify it took ??? seconds
|
||||
## TODO: time out after ??? seconds and fail this test
|
|
@ -7,12 +7,14 @@ from boinc import *
|
|||
|
||||
# test makes sure that testing framework is sane
|
||||
|
||||
def read_url(url):
|
||||
def read_url(url, quiet=False):
|
||||
'''return 1 line from url'''
|
||||
verbose_echo(2, " reading url: "+url)
|
||||
try:
|
||||
return urllib.URLopener().open(url).readline().strip()
|
||||
except IOError, e:
|
||||
error("couldn't access HTML_URL: %s %s" % (HTML_URL, e))
|
||||
if not quiet:
|
||||
error("couldn't access url: %s %s" % (url, e))
|
||||
return ''
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
@ -35,6 +37,7 @@ if __name__ == '__main__':
|
|||
|
||||
html_path = os.path.join(HTML_DIR, 'test_sanity.txt')
|
||||
html_url = os.path.join(HTML_URL, 'test_sanity.txt')
|
||||
html_proxy_url = proxerize(html_url)
|
||||
cgi_path = os.path.join(CGI_DIR, 'test_sanity_cgi')
|
||||
cgi_url = os.path.join(CGI_URL, 'test_sanity_cgi')
|
||||
|
||||
|
@ -43,6 +46,23 @@ if __name__ == '__main__':
|
|||
if read_url(html_url) != magic:
|
||||
error("couldn't access a file I just wrote: "+html_path+"\n using url: "+html_url)
|
||||
|
||||
verbose_echo(1, "Checking proxy setup")
|
||||
if read_url(html_proxy_url, quiet=True):
|
||||
error("Another proxy already running")
|
||||
else:
|
||||
proxy = Proxy('')
|
||||
if read_url(html_proxy_url) != magic:
|
||||
error("couldn't access file using proxy url: "+html_proxy_url)
|
||||
else:
|
||||
proxy.stop()
|
||||
|
||||
proxy = Proxy('exit 1 if $nconnections < 2; if_done_kill(); if_done_ping();')
|
||||
if read_url(html_proxy_url, quiet=True):
|
||||
error("Proxy should have closed connection #1")
|
||||
if read_url(html_proxy_url) != magic:
|
||||
error("Proxy should have allowed connection #2")
|
||||
proxy.stop()
|
||||
|
||||
os.unlink(html_path)
|
||||
|
||||
verbose_echo(1, "Checking webserver setup: cgi")
|
||||
|
|
Loading…
Reference in New Issue