Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
emscripten-core
GitHub Repository: emscripten-core/emscripten
Path: blob/main/tools/emcoverage.py
6173 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 contextlib
33
import errno
34
import os
35
import shutil
36
import sys
37
import uuid
38
from glob import glob
39
40
import coverage.cmdline # type: ignore
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