diff --git a/index.html b/index.html
new file mode 100644
index 0000000..1760cab
--- /dev/null
+++ b/index.html
@@ -0,0 +1,235 @@
+
+
+
+ Test scheduler
+
+
+
+
+
+
\ No newline at end of file
diff --git a/process_zip.sh b/process_zip.sh
index fd19078..fafaca0 100755
--- a/process_zip.sh
+++ b/process_zip.sh
@@ -60,9 +60,12 @@ function run() {
;;
esac
- CMD="PYTHONPATH=\$PYTHONPATH:$(pwd) python3 './templates/$TEMPLATE/test' '$TEST_PATH' > '$TEST_PATH/test.stdout.log' 2> '$TEST_PATH/test.stderr.log'"
- printf -v CMD "%q" "$CMD"
- flock "$QUEUE_PATH" bash -c "echo $CMD >> \"$QUEUE_PATH\""
+ curl \
+ --request 'POST' \
+ --header "Content-Type: application/json" \
+ --header "Authorization: OAuth ecP9ZsoKMPui4akg1MyGoT7yoGR2bLPo" \
+ --data "{\"path\":\"$(realpath $TEST_PATH)\",\"template\":\"$TEMPLATE\"}" \
+ "http://127.0.0.1:5002/schedule_test"
done
diff --git a/templates/f7/test b/templates/f7/test
index 7b6f8f6..387fced 100755
--- a/templates/f7/test
+++ b/templates/f7/test
@@ -20,10 +20,7 @@ def get_serial():
if p.serial_number == '00000000'
]
devices.sort()
- return serial.Serial(
- devices[0],
- baudrate=115200,
- timeout=5)
+ return devices[0]
class F7(DeviceUnderTestAeadUARTP):
@@ -34,6 +31,10 @@ class F7(DeviceUnderTestAeadUARTP):
self.uart_device = get_serial()
devname = os.path.basename(self.uart_device)
+ self.ser = serial.Serial(
+ self.uart_device,
+ baudrate=115200,
+ timeout=5)
self.lock = FileMutex('/var/lock/lwc-compare.%s.lock' % devname)
self.build_dir = build_dir
self.template_path = os.path.dirname(sys.argv[0])
diff --git a/test-dude.py b/test-dude.py
new file mode 100644
index 0000000..76e734c
--- /dev/null
+++ b/test-dude.py
@@ -0,0 +1,181 @@
+#!/usr/bin/env python3
+
+
+import os
+import datetime
+import threading
+import subprocess
+from flask import Flask, request
+from flask_restful import Resource, Api
+from flask_jsonpify import jsonify
+
+
+app = Flask(__name__, static_folder='.')
+api = Api(app)
+
+
+schedule = []
+runners = []
+
+
+class ScheduledTest:
+ def __init__(self, template, path):
+ self.template = template
+ self.path = path
+ self.state = 'SCHEDULED'
+ self.added = datetime.datetime.now()
+ self.lock = threading.Lock()
+
+ def to_dict(self):
+ return {
+ 'id': str(id(self)),
+ 'template': self.template,
+ 'state': self.state,
+ 'path': self.path,
+ 'added': self.added,
+ }
+
+
+class Runner(threading.Thread):
+ def __init__(self, template, program=None):
+ if program is None:
+ program = ['python3', './templates/%s/test' % template]
+
+ self.template = template
+ self.program = program
+
+ self.process = None
+ self.job = None
+ self.event = threading.Event()
+ threading.Thread.__init__(self)
+ self.start()
+
+ def to_dict(self):
+ return {
+ 'id': str(id(self)),
+ 'template': self.template,
+ 'program': ' '.join(self.program),
+ 'job': str(id(self.job)) if self.job is not None else None
+ }
+
+ def run(self):
+ while 1:
+ self.event.clear()
+ my_queue = [
+ s for s in schedule
+ if s.state == 'SCHEDULED'
+ and s.template == self.template
+ ]
+ my_queue.sort(key=lambda s: s.added)
+ if len(my_queue) == 0:
+ # No tasks for this thread, go to sleep
+ self.event.wait(timeout=5)
+ continue
+
+ job = my_queue[0]
+
+ with job.lock:
+ # Check if we were the first thread to choose this job
+ if job.state == 'SCHEDULED':
+ job.state = 'RUNNING'
+ self.job = job
+ else:
+ # Some other thread is running this test
+ continue
+
+ cmd = []
+ cmd += self.program
+ cmd += [self.job.path]
+ print("Executing ``%sยดยด" % ' '.join(cmd))
+ out_fd = open(os.path.join(self.job.path, 'test.stdout.log'), 'w')
+ err_fd = open(os.path.join(self.job.path, 'test.stderr.log'), 'w')
+ self.process = subprocess.Popen(
+ cmd,
+ stdout=out_fd,
+ stderr=err_fd
+ )
+ self.process.wait()
+ if self.process.returncode == 0:
+ self.job.state = 'SUCCESSFUL'
+ else:
+ self.job.state = 'FAILED'
+ self.process = None
+ self.job = None
+
+
+class Status(Resource):
+ def get(self):
+ print(request.data)
+ return jsonify({
+ 'schedule': [t.to_dict() for t in schedule],
+ 'runners': [r.to_dict() for r in runners]
+ })
+
+
+class RestartJob(Resource):
+ def get(self, job_id):
+ job = [job for job in schedule if str(id(job)) == job_id]
+ job = job[0] if len(job) > 0 else None
+ if job is None:
+ return 'Job not found', 404
+
+ with job.lock:
+ if job.state != 'RUNNING':
+ job.state = 'SCHEDULED'
+ return jsonify({'success': True})
+ else:
+ return 'Job is already running', 400
+
+
+class ScheduleJob(Resource):
+ def post(self):
+ if not request.is_json:
+ return 'Please send me JSON', 400
+ data = request.get_json()
+ print(data)
+ if 'path' not in data:
+ return 'path expected', 400
+ if 'template' not in data:
+ return 'template expected', 400
+
+ schedule.append(ScheduledTest(data['template'], data['path']))
+
+ result = {'success': True}
+ return jsonify(result)
+
+
+api.add_resource(Status, '/status')
+api.add_resource(ScheduleJob, '/schedule_test')
+api.add_resource(RestartJob, '/restart_test/')
+
+
+@app.route('/')
+def root():
+ return app.send_static_file('index.html')
+
+
+@app.route('/view_log//')
+def view_log(job_id, log_id):
+ job = [job for job in schedule if str(id(job)) == job_id]
+ job = job[0] if len(job) > 0 else None
+ if job is None:
+ return 'Job not found', 404
+
+ log_name = [
+ 'make.stdout.log', 'make.stderr.log',
+ 'test.stdout.log', 'test.stderr.log',
+ ][log_id]
+ log_path = os.path.join(job.path, log_name)
+ if not os.path.isfile(log_path):
+ return 'Log not found', 404
+ with open(log_path, 'r') as f:
+ return f.read()
+
+
+if __name__ == '__main__':
+ runners.append(Runner('maixduino'))
+ runners.append(Runner('f7'))
+ runners.append(Runner('uno'))
+ runners.append(Runner('esp32'))
+ runners.append(Runner('bluepill'))
+ app.run(port='5002')
diff --git a/test_scheduler.py b/test_scheduler.py
deleted file mode 100755
index e88f02a..0000000
--- a/test_scheduler.py
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/usr/bin/env python3
-import sys
-import time
-import fcntl
-import subprocess
-
-
-def file_pop_line(path):
- try:
- with open(path, 'rt+') as q:
- fcntl.lockf(q, fcntl.LOCK_EX)
- first = q.readline()
- if first == '':
- return None
- rest = q.read()
- q.seek(0)
- q.write(rest)
- q.truncate()
- return first
- except FileNotFoundError:
- return None
-
-
-def main(argv):
- test_queue = argv[1]
-
- while 1:
- cmd = file_pop_line(test_queue).strip()
-
- if cmd is None:
- time.sleep(5)
- else:
- print()
- print("Executing %s" % cmd)
- p = subprocess.Popen(['bash', '-c', cmd])
- p.wait()
- print()
- print("Return code is %d" % p.returncode)
- print()
-
-
-if __name__ == '__main__':
- sys.exit(main(sys.argv))