Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
emscripten-core
GitHub Repository: emscripten-core/emscripten
Path: blob/main/tools/emcoverage.py
4128 views
1
#!/usr/bin/env python3
2
# Copyright 2019 The Emscripten Authors. All rights reserved.
3
# Emscripten is available under two separate licenses, the MIT license and the
4
# University of Illinois/NCSA Open Source License. Both these licenses can be
5
# found in the LICENSE file.
6
7
"""
8
This is the Emscripten coverage tool.
9
10
Usage: emcoverage.py <help|reset|report|html|xml|COMMAND> ...
11
12
Special commands:
13
- help: show this message
14
- reset: remove all gathered coverage information
15
- report: show a quick overview of gathered coverage information
16
- html: generate coverage as a set of HTML files in ./htmlcov/
17
- xml: generate XML coverage report in ./coverage.xml
18
19
Otherwise, you can run any python script or Emscripten command, for example:
20
- emcoverage.py ./test/runner.py core0
21
- emcoverage.py emcc file1.c file2.c
22
23
Running a command under emcoverage.py will collect the code coverage
24
information. Every run under emcoverage.py is additive, and no coverage
25
information from previous runs is erased, unless explicitly done via
26
emcoverage.py reset.
27
28
To display the gathered coverage information, use one of the three subcommands:
29
report, html, xml.
30
"""
31
32
import errno
33
import os
34
import shutil
35
import sys
36
import uuid
37
from glob import glob
38
39
import coverage.cmdline # type: ignore
40
import contextlib
41
42
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
43
44
45
def main():
46
# We set EMSDK_PYTHON to point to this file, which is executable via #! line.
47
# Emscripten uses EMSDK_PYTHON to invoke all python subprocesses. By making this
48
# script run all python subprocesses, all of them will execute under the
49
# watchful eye of emcoverage.py, and resulting in their code coverage being
50
# tracked.
51
os.environ['EMSDK_PYTHON'] = os.path.abspath(__file__)
52
53
store = os.path.join(SCRIPT_DIR, 'coverage')
54
55
if len(sys.argv) < 2 or sys.argv[1] == 'help':
56
print(__doc__.replace('emcoverage.py', sys.argv[0]).strip())
57
return
58
59
if sys.argv[1] == 'reset':
60
shutil.rmtree(store)
61
return
62
63
if sys.argv[1] in ('html', 'report', 'xml'):
64
old_argv = sys.argv
65
sys.argv = ['coverage', 'combine'] + glob(os.path.join(store, '*'))
66
with contextlib.suppress(SystemExit):
67
coverage.cmdline.main()
68
sys.argv = old_argv + ['-i']
69
return coverage.cmdline.main()
70
71
if not os.path.exists(sys.argv[1]):
72
# If argv[1] is not a file path, instead try to interpret it as an emscripten command.
73
# This allows `emcoverage.py emcc` or `emcoverage.py embuilder` to work.
74
sys.argv[1] = os.path.join(os.path.dirname(sys.executable), '..', sys.argv[1] + '.py')
75
76
try:
77
os.mkdir(store)
78
except OSError as e:
79
if e.errno != errno.EEXIST:
80
raise
81
os.environ['COVERAGE_FILE'] = os.path.join(store, str(uuid.uuid4()))
82
sys.argv[0:1] = ['coverage', 'run', '--parallel-mode', '--']
83
84
return coverage.cmdline.main()
85
86
87
if __name__ == '__main__':
88
sys.exit(main())
89
90