diff --git a/pykat/testing/test.py b/pykat/testing/test.py index 152b9b92d6c7ead15e582ccefd0204509d5fb036..b3fc95c8a0549603ab513b98bcdd8728e01d24e9 100644 --- a/pykat/testing/test.py +++ b/pykat/testing/test.py @@ -29,14 +29,15 @@ class DiffException(Exception): self.outfile = outfile def runcmd(args): - p = sub.Popen(args, stdout=sub.PIPE, stderr=sub.PIPE) - out, err = p.communicate() - - if p.returncode != 0: - print err - raise RunException(p.returncode, args, err, out) + p = sub.Popen(args, stdout=sub.PIPE, stderr=sub.PIPE) + out, err = p.communicate() + + if p.returncode != 0: + print "STDERR: " + err + print "STDOUT: " + out + raise RunException(p.returncode, args, err, out) - return [out,err] + return [out,err] class FinesseTestProcess(Thread): @@ -51,13 +52,18 @@ class FinesseTestProcess(Thread): diff_rel_eps = 1e-13 running_kat = "" 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", git_bin="",emails="", nobuild=True,*args, **kqwargs): 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.test_id = test_id self.TEST_DIR = TEST_DIR @@ -102,7 +108,11 @@ class FinesseTestProcess(Thread): self.suites.extend(suites) self.GIT_BIN = git_bin - + + def cancelCheck(self): + if self.cancelling: + raise SystemExit() + def percent_done(self): if self.total_kats == 0: return 0.0 @@ -126,29 +136,44 @@ class FinesseTestProcess(Thread): self.built = False - print type(self.nobuild), self.nobuild - - if not os.path.exists("build"): - os.mkdir("build") - + BUILD_PATH = os.path.join(self.BASE_DIR, "build") + # Firstly we need to build the latest version of finesse - if os.path.isdir("build") and not self.nobuild: - print "deleting build dir..." - shutil.rmtree("build") + if not self.nobuild: + print "deleting build dir..." + BUILD_PATH + if os.path.exists(BUILD_PATH): + shutil.rmtree(BUILD_PATH) 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") - print "Checking out and building develop version of finesse..." + os.chdir(BUILD_PATH) + print "Checking out and building develop version of finesse " + self.git_commit + + SRC_PATH = os.path.join(BUILD_PATH,"src") 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"]) + self.cancelCheck() else: - EXE = "" 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"]) + self.cancelCheck() os.chdir(self.BASE_DIR) @@ -156,7 +181,7 @@ class FinesseTestProcess(Thread): # check if kat runs 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 @@ -172,14 +197,18 @@ class FinesseTestProcess(Thread): os.environ["KATINI"] = os.path.join(self.TEST_DIR,"kat.ini") + self.cancelCheck() # Clean up and pull latest test repository print "Cleaning test repository..." os.chdir(self.TEST_DIR) utils.git(["clean","-xdf"]) + self.cancelCheck() utils.git(["reset","--hard"]) + self.cancelCheck() print "Pulling latest test..." utils.git(["pull"]) - + self.cancelCheck() + # Define storage structures for generating report later kat_run_exceptions = {} output_differences = {} @@ -201,8 +230,9 @@ class FinesseTestProcess(Thread): if files.endswith(".kat"): self.total_kats += 1 print self.total_kats - + for suite in self.suites: + self.cancelCheck() print "Running suite: " + suite + "..." kats = [] os.chdir(os.path.join(self.TEST_DIR,"kat_test",suite)) @@ -217,6 +247,7 @@ class FinesseTestProcess(Thread): self.running_suite = suite for kat in kats: + self.cancelCheck() self.running_kat = kat print self.get_progress() @@ -237,6 +268,8 @@ class FinesseTestProcess(Thread): finally: self.done_kats += 1 + self.cancelCheck() + for suite in self.suites: if len(kat_run_exceptions[suite].keys()) > 0: print "Could not run the following kats:\n" + "\n".join(kat_run_exceptions.keys()) + " in " + suite @@ -246,6 +279,7 @@ class FinesseTestProcess(Thread): # Now we have generated the output files compare them to the references for suite in self.suites: + self.cancelCheck() print "Diffing suite: " + suite + "..." outs = [] @@ -259,7 +293,9 @@ class FinesseTestProcess(Thread): if not os.path.exists(REF_DIR): raise Exception("Suite reference directory doesn't exist: " + REF_DIR) + for out in outs: + self.cancelCheck() #print "Diffing " + out ref_file = os.path.join(REF_DIR,out) @@ -295,6 +331,8 @@ class FinesseTestProcess(Thread): reportname = today.strftime('%d%m%y') print "Writing report to " + reportname + self.cancelCheck() + f = open(reportname,'w') f.write("Python Nightly Test\n") f.write(today.strftime('%A, %d. %B %Y %I:%M%p') + "\n") @@ -326,6 +364,8 @@ class FinesseTestProcess(Thread): f.close() + self.cancelCheck() + if self.emails: if isError: diff --git a/pykat/testing/utils.py b/pykat/testing/utils.py index 2e1c6a95b676418ad139ee9777a452db87ac2612..007585ba12ee50b9204fb563f671f8835ec49a96 100644 --- a/pykat/testing/utils.py +++ b/pykat/testing/utils.py @@ -19,11 +19,16 @@ def git(args): else: cmd = GIT_BIN + " " + args + print cmd + + print os.getcwd() + p = sub.Popen(cmd, stdout=sub.PIPE, stderr=sub.PIPE) out, err = p.communicate() - + if p.returncode != 0: - print err + print "STDERR: " + err + print "STDOUT: " + err raise RunException(p.returncode, args, err, out) return [out, err] diff --git a/pykat/testing/web/templates/finesse_test.html b/pykat/testing/web/templates/finesse_test.html index c02fd0b81a78eda58324ec407e7c5ed0e1a5f3f3..faf5d89273edcda2e9155ca654735b3c87f2c2fa 100644 --- a/pykat/testing/web/templates/finesse_test.html +++ b/pykat/testing/web/templates/finesse_test.html @@ -15,6 +15,7 @@ Test status: <span id="txtStatus"></span> <div id="current_test_progress" style="width:500px;"></div> <input type="button" value="Refresh" id="btnGetProgress"/> + <input type="button" value="Cancel" id="btnCancelCurrent"/> </div> <div class="queued_tests"> @@ -37,10 +38,14 @@ <div class="new_test"> <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> - <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"/> </div> @@ -52,7 +57,7 @@ <script type="text/JavaScript"> $(document).ready(function(){ - updateLogEntries(); + updateBranches(); window.setInterval(function(){ updateQueuedTests(); @@ -70,6 +75,12 @@ }); $("#btnGetLogs").click(function(){ + $("#branch_list").empty(); + updateBranches(); + }); + + $("#branch_list").change(function(){ + $("#commit_list").empty(); updateLogEntries(); }); @@ -81,6 +92,7 @@ updateProgress(); }); + function updateProgress(){ $.ajax({ type: "POST", @@ -88,14 +100,28 @@ url: "/finesse/get_test_progress", success: function (data) { - if(data.running){ + if(data.cancelling){ + $('#btnCancelCurrent').attr("disabled", true); $('#txtGitVersion').text(data.version); - $('#txtStatus').text(data.status); + $('#txtStatus').text("CANCELLING AT NEXT CHANCE - " + data.status); $( "#current_test_progress" ).progressbar({ value: data.percent }); } else { - $('#txtGitVersion').text("N/A"); - $('#txtStatus').text("No test running"); - $( "#current_test_progress" ).progressbar({ value: false }); + if(data.running){ + $('#txtGitVersion').text(data.version); + $('#txtStatus').text(data.status); + $("#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 { + $('#btnCancelCurrent').attr("disabled", true); + $('#txtGitVersion').text("N/A"); + $('#txtStatus').text("No test running"); + $( "#current_test_progress" ).progressbar({ value: false }); + } } }, error: function(jqXHR, textStatus, err){ @@ -105,6 +131,20 @@ }); } + function cancelTest(id){ + $.ajax({ + type: "POST", + contentType: "application/json; charset=utf-8", + url: "/finesse/cancel_test_" + id, + success: function () { + }, + error: function(jqXHR, textStatus, err){ + console.log('error: ' + err); + }, + dataType: "json" + }); + } + function startNewTest(){ list = $("#commit_list"); @@ -160,7 +200,7 @@ rows += '<td>'+ tests[i].id + '</td>'; rows += '<td>'+ tests[i].queue_time +'</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>'; tbl.append(rows); @@ -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(){ + $("#btnStartTest").attr("disabled", true); list = $("#commit_list"); - - list.empty(); $.ajax({ type: "POST", contentType: "application/json; charset=utf-8", - url: "/finesse/get_50_logs", + url: "/finesse/get_50_" + $("#branch_list").val() + "_logs", success: function (data) { logs = data.logs; + list.empty(); for(var i=0; i<logs.length; i++){ list.append($('<option>', { value: logs[i].commit, text: logs[i].commit + " - " + logs[i].message})); } + $("#btnStartTest").attr("disabled", false); }, error: function(jqXHR, textStatus, err){ console.log('error: ' + err); diff --git a/pykat/testing/web/web_interface.py b/pykat/testing/web/web_interface.py index 7b1148bf31e98fba1639630ba1f561dd00acfb70..20a9052de017d2b6610561e83f9245c762f862d9 100644 --- a/pykat/testing/web/web_interface.py +++ b/pykat/testing/web/web_interface.py @@ -68,9 +68,47 @@ class FinesseProcessWatcher(Thread): current_test = None 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('/') def home_page(): @@ -105,7 +143,7 @@ def finesse_start_test(): TEST_RUN_PATH, git_commit, run_fast=False, suites=[], test_id=test_id, - emails="", nobuild=True) + emails="", nobuild=False) # check if anything is running and if it # isn't start this test off @@ -148,21 +186,46 @@ def finesse_get_test_progress(): return jsonify(running=False) else: - + test_id = current_test.test_id + cancelling = current_test.cancelling percent_done = current_test.percent_done() status = current_test.get_progress() 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: 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) -@app.route('/finesse/get_<count>_logs', methods=['POST']) -def finesse_get_log(count): - [out,err] = utils.git("--git-dir ./finesse_src/.git pull") + branches = list() + + for b in out.split("\n"): + vals = b.split("/") + if len(vals) >= 3: + branches.append(vals[2].split(" ")[0]) + + return jsonify(branches=branches) + +@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("--git-dir ./finesse_src/.git log --max-count={0} --pretty=oneline".format(count)) + [out,err] = utils.git("log --max-count={0} --pretty=oneline".format(count)) log_entries = out.split("\n") @@ -182,4 +245,5 @@ def finesse_get_log(count): return jsonify(logs=log2send) - \ No newline at end of file + + \ No newline at end of file diff --git a/pykat/testing/web_server.py b/pykat/testing/web_server.py index d5fd15660915e767778f745e08f1d6b2f0f1abb9..2d57324e4843c8c4c342c9b58db892ae5e294f4f 100644 --- a/pykat/testing/web_server.py +++ b/pykat/testing/web_server.py @@ -3,7 +3,7 @@ import sys from flask import Flask from pykat.testing import utils -def start(instance_path,port=5000, debug=True): +def start(instance_path,port=5000, debug=False): global app print "starting web server..." @@ -31,8 +31,9 @@ def start(instance_path,port=5000, debug=True): print "finesse src folder didn't exist, cloning now..." utils.git("clone git://gitmaster.atlas.aei.uni-hannover.de/finesse/src.git finesse_src") else: + os.chdir(os.path.join(app.instance_path,"finesse_src")) # get the latest version for logs etc. - utils.git("--git-dir ./finesse_src/.git pull") + utils.git("pull") # need local copy of test if not os.path.exists("./finesse_test"):