Skip to content
Snippets Groups Projects
Commit edf77fbf authored by Daniel Brown's avatar Daniel Brown
Browse files

added cancellation of test and branch picker

parent 93ba0dd3
No related branches found
No related tags found
No related merge requests found
...@@ -33,7 +33,8 @@ def runcmd(args): ...@@ -33,7 +33,8 @@ def runcmd(args):
out, err = p.communicate() out, err = p.communicate()
if p.returncode != 0: if p.returncode != 0:
print err print "STDERR: " + err
print "STDOUT: " + out
raise RunException(p.returncode, args, err, out) raise RunException(p.returncode, args, err, out)
return [out,err] return [out,err]
...@@ -51,13 +52,18 @@ class FinesseTestProcess(Thread): ...@@ -51,13 +52,18 @@ class FinesseTestProcess(Thread):
diff_rel_eps = 1e-13 diff_rel_eps = 1e-13
running_kat = "" running_kat = ""
running_suite = "" running_suite = ""
cancelling = False
def __init__(self, TEST_DIR, BASE_DIR, git_commit, def __init__(self, TEST_DIR, BASE_DIR, test_commit,
run_fast=False, suites=[], test_id="0", run_fast=False, suites=[], test_id="0",
git_bin="",emails="", nobuild=True,*args, **kqwargs): git_bin="",emails="", nobuild=True,*args, **kqwargs):
Thread.__init__(self) Thread.__init__(self)
self.git_commit = git_commit self.git_commit = test_commit
if test_commit is None:
raise Exception("A git commit ID must be provided for the test")
self.queue_time = datetime.now() self.queue_time = datetime.now()
self.test_id = test_id self.test_id = test_id
self.TEST_DIR = TEST_DIR self.TEST_DIR = TEST_DIR
...@@ -103,6 +109,10 @@ class FinesseTestProcess(Thread): ...@@ -103,6 +109,10 @@ class FinesseTestProcess(Thread):
self.GIT_BIN = git_bin self.GIT_BIN = git_bin
def cancelCheck(self):
if self.cancelling:
raise SystemExit()
def percent_done(self): def percent_done(self):
if self.total_kats == 0: if self.total_kats == 0:
return 0.0 return 0.0
...@@ -126,29 +136,44 @@ class FinesseTestProcess(Thread): ...@@ -126,29 +136,44 @@ class FinesseTestProcess(Thread):
self.built = False self.built = False
print type(self.nobuild), self.nobuild BUILD_PATH = os.path.join(self.BASE_DIR, "build")
if not os.path.exists("build"):
os.mkdir("build")
# Firstly we need to build the latest version of finesse # Firstly we need to build the latest version of finesse
if os.path.isdir("build") and not self.nobuild: if not self.nobuild:
print "deleting build dir..." print "deleting build dir..." + BUILD_PATH
shutil.rmtree("build") if os.path.exists(BUILD_PATH):
shutil.rmtree(BUILD_PATH)
print "Checking out finesse base..." print "Checking out finesse base..."
utils.git(["clone","git://gitmaster.atlas.aei.uni-hannover.de/finesse/base.git","build"]) utils.git(["clone","git://gitmaster.atlas.aei.uni-hannover.de/finesse/base.git",BUILD_PATH])
os.chdir("build") os.chdir(BUILD_PATH)
print "Checking out and building develop version of finesse..." print "Checking out and building develop version of finesse " + self.git_commit
SRC_PATH = os.path.join(BUILD_PATH,"src")
if sys.platform == "win32": if sys.platform == "win32":
runcmd(["bash","./finesse.sh","--checkout","develop"]) runcmd(["bash","./finesse.sh","--checkout"])
self.cancelCheck()
os.chdir(SRC_PATH)
utils.git(["checkout",self.git_commit])
self.cancelCheck()
os.chdir(BUILD_PATH)
runcmd(["bash","./finesse.sh","--build"]) runcmd(["bash","./finesse.sh","--build"])
self.cancelCheck()
else: else:
EXE = ""
runcmd(["./finesse.sh","--checkout","develop"]) runcmd(["./finesse.sh","--checkout","develop"])
self.cancelCheck()
os.chdir(SRC_PATH)
utils.git(["checkout",self.git_commit])
self.cancelCheck()
os.chdir(BUILD_PATH)
runcmd(["./finesse.sh","--build"]) runcmd(["./finesse.sh","--build"])
self.cancelCheck()
os.chdir(self.BASE_DIR) os.chdir(self.BASE_DIR)
...@@ -156,7 +181,7 @@ class FinesseTestProcess(Thread): ...@@ -156,7 +181,7 @@ class FinesseTestProcess(Thread):
# check if kat runs # check if kat runs
if not os.path.exists(FINESSE_EXE): if not os.path.exists(FINESSE_EXE):
raise Exception("Kat file was not found") raise Exception("Kat file was not found in " + FINESSE_EXE)
self.built = True self.built = True
...@@ -172,13 +197,17 @@ class FinesseTestProcess(Thread): ...@@ -172,13 +197,17 @@ class FinesseTestProcess(Thread):
os.environ["KATINI"] = os.path.join(self.TEST_DIR,"kat.ini") os.environ["KATINI"] = os.path.join(self.TEST_DIR,"kat.ini")
self.cancelCheck()
# Clean up and pull latest test repository # Clean up and pull latest test repository
print "Cleaning test repository..." print "Cleaning test repository..."
os.chdir(self.TEST_DIR) os.chdir(self.TEST_DIR)
utils.git(["clean","-xdf"]) utils.git(["clean","-xdf"])
self.cancelCheck()
utils.git(["reset","--hard"]) utils.git(["reset","--hard"])
self.cancelCheck()
print "Pulling latest test..." print "Pulling latest test..."
utils.git(["pull"]) utils.git(["pull"])
self.cancelCheck()
# Define storage structures for generating report later # Define storage structures for generating report later
kat_run_exceptions = {} kat_run_exceptions = {}
...@@ -203,6 +232,7 @@ class FinesseTestProcess(Thread): ...@@ -203,6 +232,7 @@ class FinesseTestProcess(Thread):
print self.total_kats print self.total_kats
for suite in self.suites: for suite in self.suites:
self.cancelCheck()
print "Running suite: " + suite + "..." print "Running suite: " + suite + "..."
kats = [] kats = []
os.chdir(os.path.join(self.TEST_DIR,"kat_test",suite)) os.chdir(os.path.join(self.TEST_DIR,"kat_test",suite))
...@@ -217,6 +247,7 @@ class FinesseTestProcess(Thread): ...@@ -217,6 +247,7 @@ class FinesseTestProcess(Thread):
self.running_suite = suite self.running_suite = suite
for kat in kats: for kat in kats:
self.cancelCheck()
self.running_kat = kat self.running_kat = kat
print self.get_progress() print self.get_progress()
...@@ -237,6 +268,8 @@ class FinesseTestProcess(Thread): ...@@ -237,6 +268,8 @@ class FinesseTestProcess(Thread):
finally: finally:
self.done_kats += 1 self.done_kats += 1
self.cancelCheck()
for suite in self.suites: for suite in self.suites:
if len(kat_run_exceptions[suite].keys()) > 0: if len(kat_run_exceptions[suite].keys()) > 0:
print "Could not run the following kats:\n" + "\n".join(kat_run_exceptions.keys()) + " in " + suite print "Could not run the following kats:\n" + "\n".join(kat_run_exceptions.keys()) + " in " + suite
...@@ -246,6 +279,7 @@ class FinesseTestProcess(Thread): ...@@ -246,6 +279,7 @@ class FinesseTestProcess(Thread):
# Now we have generated the output files compare them to the references # Now we have generated the output files compare them to the references
for suite in self.suites: for suite in self.suites:
self.cancelCheck()
print "Diffing suite: " + suite + "..." print "Diffing suite: " + suite + "..."
outs = [] outs = []
...@@ -259,7 +293,9 @@ class FinesseTestProcess(Thread): ...@@ -259,7 +293,9 @@ class FinesseTestProcess(Thread):
if not os.path.exists(REF_DIR): if not os.path.exists(REF_DIR):
raise Exception("Suite reference directory doesn't exist: " + REF_DIR) raise Exception("Suite reference directory doesn't exist: " + REF_DIR)
for out in outs: for out in outs:
self.cancelCheck()
#print "Diffing " + out #print "Diffing " + out
ref_file = os.path.join(REF_DIR,out) ref_file = os.path.join(REF_DIR,out)
...@@ -295,6 +331,8 @@ class FinesseTestProcess(Thread): ...@@ -295,6 +331,8 @@ class FinesseTestProcess(Thread):
reportname = today.strftime('%d%m%y') reportname = today.strftime('%d%m%y')
print "Writing report to " + reportname print "Writing report to " + reportname
self.cancelCheck()
f = open(reportname,'w') f = open(reportname,'w')
f.write("Python Nightly Test\n") f.write("Python Nightly Test\n")
f.write(today.strftime('%A, %d. %B %Y %I:%M%p') + "\n") f.write(today.strftime('%A, %d. %B %Y %I:%M%p') + "\n")
...@@ -326,6 +364,8 @@ class FinesseTestProcess(Thread): ...@@ -326,6 +364,8 @@ class FinesseTestProcess(Thread):
f.close() f.close()
self.cancelCheck()
if self.emails: if self.emails:
if isError: if isError:
......
...@@ -19,11 +19,16 @@ def git(args): ...@@ -19,11 +19,16 @@ def git(args):
else: else:
cmd = GIT_BIN + " " + args cmd = GIT_BIN + " " + args
print cmd
print os.getcwd()
p = sub.Popen(cmd, stdout=sub.PIPE, stderr=sub.PIPE) p = sub.Popen(cmd, stdout=sub.PIPE, stderr=sub.PIPE)
out, err = p.communicate() out, err = p.communicate()
if p.returncode != 0: if p.returncode != 0:
print err print "STDERR: " + err
print "STDOUT: " + err
raise RunException(p.returncode, args, err, out) raise RunException(p.returncode, args, err, out)
return [out, err] return [out, err]
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
Test status: <span id="txtStatus"></span> Test status: <span id="txtStatus"></span>
<div id="current_test_progress" style="width:500px;"></div> <div id="current_test_progress" style="width:500px;"></div>
<input type="button" value="Refresh" id="btnGetProgress"/> <input type="button" value="Refresh" id="btnGetProgress"/>
<input type="button" value="Cancel" id="btnCancelCurrent"/>
</div> </div>
<div class="queued_tests"> <div class="queued_tests">
...@@ -37,10 +38,14 @@ ...@@ -37,10 +38,14 @@
<div class="new_test"> <div class="new_test">
<h2>Start new test</h2> <h2>Start new test</h2>
<select id="branch_list" style="width: 100px;">
<option text="develop" value="develop"/>
</select>
<select id="commit_list" style="width: 300px;"> <select id="commit_list" style="width: 300px;">
</select> </select>
<input type="button" value="Refresh log entries" id="btnGetLogs"/> <input type="button" value="Refresh" id="btnGetLogs"/>
<input type="button" value="Start new FINESSSE test" id="btnStartTest"/> <input type="button" value="Start new FINESSSE test" id="btnStartTest"/>
</div> </div>
...@@ -52,7 +57,7 @@ ...@@ -52,7 +57,7 @@
<script type="text/JavaScript"> <script type="text/JavaScript">
$(document).ready(function(){ $(document).ready(function(){
updateLogEntries(); updateBranches();
window.setInterval(function(){ window.setInterval(function(){
updateQueuedTests(); updateQueuedTests();
...@@ -70,6 +75,12 @@ ...@@ -70,6 +75,12 @@
}); });
$("#btnGetLogs").click(function(){ $("#btnGetLogs").click(function(){
$("#branch_list").empty();
updateBranches();
});
$("#branch_list").change(function(){
$("#commit_list").empty();
updateLogEntries(); updateLogEntries();
}); });
...@@ -81,6 +92,7 @@ ...@@ -81,6 +92,7 @@
updateProgress(); updateProgress();
}); });
function updateProgress(){ function updateProgress(){
$.ajax({ $.ajax({
type: "POST", type: "POST",
...@@ -88,15 +100,43 @@ ...@@ -88,15 +100,43 @@
url: "/finesse/get_test_progress", url: "/finesse/get_test_progress",
success: function (data) { success: function (data) {
if(data.cancelling){
$('#btnCancelCurrent').attr("disabled", true);
$('#txtGitVersion').text(data.version);
$('#txtStatus').text("CANCELLING AT NEXT CHANCE - " + data.status);
$( "#current_test_progress" ).progressbar({ value: data.percent });
} else {
if(data.running){ if(data.running){
$('#txtGitVersion').text(data.version); $('#txtGitVersion').text(data.version);
$('#txtStatus').text(data.status); $('#txtStatus').text(data.status);
$("#current_test_progress").progressbar({ value: data.percent }); $("#current_test_progress").progressbar({ value: data.percent });
$('#btnCancelCurrent').attr("disabled", false);
$('#btnCancelCurrent').unbind('click');
$('#btnCancelCurrent').click(function(){
$('#btnCancelCurrent').attr("disabled", true);
cancelTest(data.id);
});
} else { } else {
$('#btnCancelCurrent').attr("disabled", true);
$('#txtGitVersion').text("N/A"); $('#txtGitVersion').text("N/A");
$('#txtStatus').text("No test running"); $('#txtStatus').text("No test running");
$( "#current_test_progress" ).progressbar({ value: false }); $( "#current_test_progress" ).progressbar({ value: false });
} }
}
},
error: function(jqXHR, textStatus, err){
console.log('error: ' + err);
},
dataType: "json"
});
}
function cancelTest(id){
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: "/finesse/cancel_test_" + id,
success: function () {
}, },
error: function(jqXHR, textStatus, err){ error: function(jqXHR, textStatus, err){
console.log('error: ' + err); console.log('error: ' + err);
...@@ -160,7 +200,7 @@ ...@@ -160,7 +200,7 @@
rows += '<td>'+ tests[i].id + '</td>'; rows += '<td>'+ tests[i].id + '</td>';
rows += '<td>'+ tests[i].queue_time +'</td>'; rows += '<td>'+ tests[i].queue_time +'</td>';
rows += '<td>'+ tests[i].git_commit +'</td>'; rows += '<td>'+ tests[i].git_commit +'</td>';
rows += '<td>'; rows += '<td><input type="button" value="Cancel" onclick="cancelTest(' + tests[i].id + ');"'+ +'</td>';
rows += '</tr>'; rows += '</tr>';
tbl.append(rows); tbl.append(rows);
...@@ -176,21 +216,48 @@ ...@@ -176,21 +216,48 @@
}); });
} }
function updateBranches(){
$("#btnStartTest").attr("disabled", true);
blist = $("#branch_list");
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: "/finesse/get_branches",
success: function (data) {
branches = data.branches;
blist.empty();
for(var i=0; i<branches.length; i++){
blist.append($('<option>', { value: branches[i], text: branches[i]}));
}
updateLogEntries();
},
error: function(jqXHR, textStatus, err){
console.log('error: ' + err);
},
dataType: "json"
});
}
function updateLogEntries(){ function updateLogEntries(){
$("#btnStartTest").attr("disabled", true);
list = $("#commit_list"); list = $("#commit_list");
list.empty();
$.ajax({ $.ajax({
type: "POST", type: "POST",
contentType: "application/json; charset=utf-8", contentType: "application/json; charset=utf-8",
url: "/finesse/get_50_logs", url: "/finesse/get_50_" + $("#branch_list").val() + "_logs",
success: function (data) { success: function (data) {
logs = data.logs; logs = data.logs;
list.empty();
for(var i=0; i<logs.length; i++){ for(var i=0; i<logs.length; i++){
list.append($('<option>', { value: logs[i].commit, text: logs[i].commit + " - " + logs[i].message})); list.append($('<option>', { value: logs[i].commit, text: logs[i].commit + " - " + logs[i].message}));
} }
$("#btnStartTest").attr("disabled", false);
}, },
error: function(jqXHR, textStatus, err){ error: function(jqXHR, textStatus, err){
console.log('error: ' + err); console.log('error: ' + err);
......
...@@ -69,8 +69,46 @@ class FinesseProcessWatcher(Thread): ...@@ -69,8 +69,46 @@ class FinesseProcessWatcher(Thread):
schedule_lock.release() schedule_lock.release()
@app.route('/finesse/cancel_test_<id>', methods=["POST"])
def finesse_cancel_test(id):
print id
if int(id) >= 0:
id = int(id)
print "Cancelling " + str(id)
try:
# get lock here so that watcher doesn't interfere
# with removing/starting new tests
schedule_lock.acquire()
print current_test
if current_test is not None:
print "cid " + str(current_test.test_id)
if current_test.test_id == id:
current_test.cancelling = True
print "Cancelling Current Test"
return str(id)
ix = 0
remove = -1;
for t in scheduled_tests:
if t.test_id == id:
remove = ix
break
ix += 1
if remove > -1:
print "Cancelled queued test"
scheduled_tests.pop(remove)
return str(id)
print "Nothing cancelled"
return "0"
finally:
schedule_lock.release()
@app.route('/') @app.route('/')
def home_page(): def home_page():
...@@ -105,7 +143,7 @@ def finesse_start_test(): ...@@ -105,7 +143,7 @@ def finesse_start_test():
TEST_RUN_PATH, TEST_RUN_PATH,
git_commit, git_commit,
run_fast=False, suites=[], test_id=test_id, run_fast=False, suites=[], test_id=test_id,
emails="", nobuild=True) emails="", nobuild=False)
# check if anything is running and if it # check if anything is running and if it
# isn't start this test off # isn't start this test off
...@@ -148,21 +186,46 @@ def finesse_get_test_progress(): ...@@ -148,21 +186,46 @@ def finesse_get_test_progress():
return jsonify(running=False) return jsonify(running=False)
else: else:
test_id = current_test.test_id
cancelling = current_test.cancelling
percent_done = current_test.percent_done() percent_done = current_test.percent_done()
status = current_test.get_progress() status = current_test.get_progress()
version = current_test.get_version() version = current_test.get_version()
return jsonify(running=True, percent=percent_done, status=status, version=version) return jsonify(cancelling=cancelling, running=True, id=test_id, percent=percent_done, status=status, version=version)
finally: finally:
schedule_lock.release() schedule_lock.release()
@app.route('/finesse/get_branches', methods=["POST"])
def finesse_get_branches():
os.chdir(os.path.join(app.instance_path,"finesse_src"))
try:
[out,err] = utils.git("branch -a")
except Exception as ex:
print "git branch error : " + str(ex)
branches = list()
for b in out.split("\n"):
vals = b.split("/")
if len(vals) >= 3:
branches.append(vals[2].split(" ")[0])
@app.route('/finesse/get_<count>_logs', methods=['POST']) return jsonify(branches=branches)
def finesse_get_log(count):
[out,err] = utils.git("--git-dir ./finesse_src/.git pull")
[out,err] = utils.git("--git-dir ./finesse_src/.git log --max-count={0} --pretty=oneline".format(count)) @app.route('/finesse/get_<count>_<branch>_logs', methods=['POST'])
def finesse_get_log(count,branch):
os.chdir(os.path.join(app.instance_path,"finesse_src"))
print "!!!!", count, branch
try:
[out,err] = utils.git("checkout " + branch)
[out,err] = utils.git("pull")
except Exception as ex:
print "git pull error : " + str(ex)
[out,err] = utils.git("log --max-count={0} --pretty=oneline".format(count))
log_entries = out.split("\n") log_entries = out.split("\n")
...@@ -183,3 +246,4 @@ def finesse_get_log(count): ...@@ -183,3 +246,4 @@ def finesse_get_log(count):
return jsonify(logs=log2send) return jsonify(logs=log2send)
\ No newline at end of file
...@@ -3,7 +3,7 @@ import sys ...@@ -3,7 +3,7 @@ import sys
from flask import Flask from flask import Flask
from pykat.testing import utils from pykat.testing import utils
def start(instance_path,port=5000, debug=True): def start(instance_path,port=5000, debug=False):
global app global app
print "starting web server..." print "starting web server..."
...@@ -31,8 +31,9 @@ def start(instance_path,port=5000, debug=True): ...@@ -31,8 +31,9 @@ def start(instance_path,port=5000, debug=True):
print "finesse src folder didn't exist, cloning now..." print "finesse src folder didn't exist, cloning now..."
utils.git("clone git://gitmaster.atlas.aei.uni-hannover.de/finesse/src.git finesse_src") utils.git("clone git://gitmaster.atlas.aei.uni-hannover.de/finesse/src.git finesse_src")
else: else:
os.chdir(os.path.join(app.instance_path,"finesse_src"))
# get the latest version for logs etc. # get the latest version for logs etc.
utils.git("--git-dir ./finesse_src/.git pull") utils.git("pull")
# need local copy of test # need local copy of test
if not os.path.exists("./finesse_test"): if not os.path.exists("./finesse_test"):
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment