Skip to content

Commit

Permalink
build HTML report from status info collect during stdlib compilation
Browse files Browse the repository at this point in the history
  • Loading branch information
eliasdorneles committed May 10, 2018
1 parent 8150cbf commit 946de60
Show file tree
Hide file tree
Showing 4 changed files with 194 additions and 19 deletions.
5 changes: 5 additions & 0 deletions stdlib_tests/test_colorsys.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import colorsys


print(colorsys.rgb_to_hls(256, 0, 0))
print(colorsys.hls_to_rgb(*colorsys.rgb_to_hls(256, 0, 0)))
4 changes: 4 additions & 0 deletions stdlib_tests/test_textwrap.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import textwrap


print(textwrap.fill('one two three four five six seven', width=10))
162 changes: 162 additions & 0 deletions tools/build_report.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Build report with stdlib modules status
"""

from __future__ import print_function, absolute_import, division
import glob
import jinja2

# ugly hack to avoid duplicating code:
import sys, os
sys.path.append(os.path.dirname(__file__))
from compile_stdlib import module_list


TEMPLATE = jinja2.Template(r"""
<html>
<head>
<title>VOC stdlib modules status</title>
<style>
body {
font: 1.2em "Open Sans", sans-serif;
}
.td {
padding: 2px 0;
border: 1px solid #444;
}
.notest {
background-color: #aaa;
}
.nocompile {
color: #ddaaaa;
background-color: #aa1111;
}
.failed {
background-color: #773333;
color: #eeaaaa;
}
.ok {
color: #aaddaa;
background-color: #11aa11;
}
pre {
display: none;
}
</style>
</head>
<body>
<table>
<tr>
<th>Module name</th>
<th>Compile</th>
<th>Test</th>
</tr>
{% for info in modules_info %}
<tr>
<td>{{ info.module }}</td>
<td class={{ info.compile_status|lower }}>
{{ info.compile_status }}
<pre>{{ info.compile_errors }}</pre>
</td>
<td class={{ info.test_status|lower }}>
{{ info.test_status }}
<pre>{{ info.test_errors }}</pre>
</td>
</tr>
{% endfor %}
</table>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
$(function(){
$('td pre').each(function() {
var pre = $(this);
var pre_text = pre.text();
if (pre_text.length > 1) {
var btn = $('<button>expand</button>');
btn.click(function(){
pre.toggle();
})
btn.insertBefore(pre);
} else {
console.log('pre', pre_text);
}
});
});
</script>
</body>
</html>
""")


def find_result(mod_name):
result_files = glob.glob(os.path.join('build', 'java', 'python', mod_name + '.*'))
result_files = [f for f in result_files
if not f.endswith('.class') and not f.endswith(mod_name)]
if not result_files:
result_files = glob.glob(os.path.join('build', 'java', 'python', mod_name,
'__init__.*'))
result_files = [f for f in result_files if not f.endswith('.class')]
if result_files:
return sorted(result_files)


def read_file(fpath):
with open(fpath) as f:
return f.read()


def build_info(mod_name, result_files):
result_files = find_result(mod_name)
compile_status = 'N/A'
test_status = 'N/A'
compile_errors = ''
test_errors = ''
if result_files:
if result_files[0].endswith('.compile-stderr'):
compile_status = 'FAILED'
compile_errors = read_file(result_files[0])
else:
compile_status = 'OK'

if result_files[0].endswith('.test-works'):
test_status = 'OK'
elif result_files[0].endswith('.test-notest'):
test_status = 'NOTEST'
elif result_files[0].endswith('.test-compile-stderr'):
test_status = 'NOCOMPILE'
test_errors = read_file(result_files[0])
elif '.test-fails' in result_files[0]:
test_status = 'FAILED'
return dict(
module=mod_name,
result_files=result_files,
compile_status=compile_status,
compile_errors=compile_errors,
test_status=test_status,
)


def run(args):
modules_info = [
build_info(mod, find_result(mod))
for mod in
sorted(module_list('java', False))
]
if args.html:
html = TEMPLATE.render(modules_info=modules_info)
with open('report.html', 'w') as f:
f.write(html)
else:
print('{:17} {:10} {:10}'.format('Module', 'Compile', 'Test'))
for info in modules_info:
print('{module:17} {compile_status:10} {test_status:10}'.format(**info))


if '__main__' == __name__:
import argparse
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('--html', action='store_true')

args = parser.parse_args()
run(args)
42 changes: 23 additions & 19 deletions tools/compile_stdlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ def run_cmd(cmd):
def run_smoke_test(mod_name, output_path):
test_path = os.path.join(REPO_ROOT, 'stdlib_tests', 'test_%s.py' % mod_name)
if not os.path.exists(test_path):
write_result_file(output_path, '.test.notest', '')
write_result_file(output_path, '.test-notest', '')
return
test_dir = os.path.join(REPO_ROOT, 'build', 'stdlib_tests')
_, stdout, stderr = run_cmd([
Expand All @@ -237,7 +237,7 @@ def run_smoke_test(mod_name, output_path):
test_path,
])
if stderr:
write_result_file(output_path, '.test.stderr', stderr)
write_result_file(output_path, '.test-compile-stderr', stderr)
else:
_, py_stdout, py_stderr = run_cmd(['python', test_path])
# XXX: fix this for multiple-levels:
Expand All @@ -248,12 +248,12 @@ def run_smoke_test(mod_name, output_path):
test_mod_name
])
if py_stdout == voc_stdout and py_stderr == voc_stderr:
write_result_file(output_path, '.test.works', stdout.decode('utf-8'))
write_result_file(output_path, '.test-works', stdout.decode('utf-8'))
else:
write_result_file(output_path, '.test.fails.voc_stdout', voc_stdout.decode('utf-8'))
write_result_file(output_path, '.test.fails.voc_stderr', voc_stderr.decode('utf-8'))
write_result_file(output_path, '.test.fails.py_stdout', py_stdout.decode('utf-8'))
write_result_file(output_path, '.test.fails.py_stderr', py_stderr.decode('utf-8'))
write_result_file(output_path, '.test-fails-voc_stdout', voc_stdout.decode('utf-8'))
write_result_file(output_path, '.test-fails-voc_stderr', voc_stderr.decode('utf-8'))
write_result_file(output_path, '.test-fails-py_stdout', py_stdout.decode('utf-8'))
write_result_file(output_path, '.test-fails-py_stderr', py_stderr.decode('utf-8'))


def _compile_module(args):
Expand All @@ -262,7 +262,7 @@ def _compile_module(args):
Save results in the queues passed by pool.map.
"""
name, target, passed, failed, fast = args
name, target, passed, failed, fast, collect_status = args

module_path = os.path.join(ouroboros_repo_folder(), 'ouroboros', name)
output_path = os.path.join(REPO_ROOT, 'build', target, 'python', name)
Expand Down Expand Up @@ -311,15 +311,15 @@ def _compile_module(args):
else:
print('F', end='', flush=True)
failed.append(name)
if not fast:
write_result_file(output_path, '.compile.stderr', stderr)
if collect_status:
write_result_file(output_path, '.compile-stderr', stderr)
else:
print('.', end='', flush=True)
passed.append(name)
if not fast:
if collect_status:
run_smoke_test(name, output_path)

def compile_modules(modules, target, fast):
def compile_modules(modules, target, fast, collect_status=False):
"""Run main compilation process on all modules found."""
pool = multiprocessing.Pool(multiprocessing.cpu_count())

Expand All @@ -328,7 +328,7 @@ def compile_modules(modules, target, fast):
failed = m.list()

args = [
(name, target, passed, failed, fast)
(name, target, passed, failed, fast, collect_status)
for name in modules
]

Expand All @@ -339,17 +339,17 @@ def compile_modules(modules, target, fast):
return passed, failed


def main(target, fast):
def main(args):
"""Run main compilation process."""
start = datetime.now()
update_repo()

# List valid files to try to compile
modules = module_list(target, fast)
modules = module_list(args.target, args.fast)
print('Compiling %s python modules...' % len(modules))

# Run compilation process
passed, failed = compile_modules(modules, target, fast)
passed, failed = compile_modules(modules, args.target, args.fast,
collect_status=args.collect_status)

print()
print("Built %s modules" % len(passed))
Expand All @@ -371,6 +371,10 @@ def main(target, fast):
action='store_true',
help="Fast compile; ignore any known-bad modules and skip already compiled files"
)
parser.add_argument(
'--collect-status',
action='store_true',
help="Run stdlib tests and collect status info of stdlib modules"
)

args = parser.parse_args()
main(target=args.target, fast=args.fast)
main(parser.parse_args())

0 comments on commit 946de60

Please sign in to comment.