jolt 0.9.76__py3-none-any.whl → 0.9.429__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- jolt/__init__.py +88 -7
- jolt/__main__.py +9 -1
- jolt/bin/fstree-darwin-x86_64 +0 -0
- jolt/bin/fstree-linux-x86_64 +0 -0
- jolt/cache.py +839 -367
- jolt/chroot.py +156 -0
- jolt/cli.py +362 -143
- jolt/common_pb2.py +63 -0
- jolt/common_pb2_grpc.py +4 -0
- jolt/config.py +99 -42
- jolt/error.py +19 -4
- jolt/expires.py +2 -2
- jolt/filesystem.py +8 -6
- jolt/graph.py +705 -117
- jolt/hooks.py +63 -1
- jolt/influence.py +129 -6
- jolt/loader.py +369 -121
- jolt/log.py +225 -63
- jolt/manifest.py +28 -38
- jolt/options.py +35 -10
- jolt/pkgs/abseil.py +42 -0
- jolt/pkgs/asio.py +25 -0
- jolt/pkgs/autoconf.py +41 -0
- jolt/pkgs/automake.py +41 -0
- jolt/pkgs/b2.py +31 -0
- jolt/pkgs/boost.py +111 -0
- jolt/pkgs/boringssl.py +32 -0
- jolt/pkgs/busybox.py +39 -0
- jolt/pkgs/bzip2.py +43 -0
- jolt/pkgs/cares.py +29 -0
- jolt/pkgs/catch2.py +36 -0
- jolt/pkgs/cbindgen.py +17 -0
- jolt/pkgs/cista.py +19 -0
- jolt/pkgs/clang.py +44 -0
- jolt/pkgs/cli11.py +23 -0
- jolt/pkgs/cmake.py +48 -0
- jolt/pkgs/cpython.py +196 -0
- jolt/pkgs/crun.py +29 -0
- jolt/pkgs/curl.py +38 -0
- jolt/pkgs/dbus.py +18 -0
- jolt/pkgs/double_conversion.py +24 -0
- jolt/pkgs/fastfloat.py +21 -0
- jolt/pkgs/ffmpeg.py +28 -0
- jolt/pkgs/flatbuffers.py +29 -0
- jolt/pkgs/fmt.py +27 -0
- jolt/pkgs/fstree.py +20 -0
- jolt/pkgs/gflags.py +18 -0
- jolt/pkgs/glib.py +18 -0
- jolt/pkgs/glog.py +25 -0
- jolt/pkgs/glslang.py +21 -0
- jolt/pkgs/golang.py +16 -11
- jolt/pkgs/googlebenchmark.py +18 -0
- jolt/pkgs/googletest.py +46 -0
- jolt/pkgs/gperf.py +15 -0
- jolt/pkgs/grpc.py +73 -0
- jolt/pkgs/hdf5.py +19 -0
- jolt/pkgs/help2man.py +14 -0
- jolt/pkgs/inja.py +28 -0
- jolt/pkgs/jsoncpp.py +31 -0
- jolt/pkgs/libarchive.py +43 -0
- jolt/pkgs/libcap.py +44 -0
- jolt/pkgs/libdrm.py +44 -0
- jolt/pkgs/libedit.py +42 -0
- jolt/pkgs/libevent.py +31 -0
- jolt/pkgs/libexpat.py +27 -0
- jolt/pkgs/libfastjson.py +21 -0
- jolt/pkgs/libffi.py +16 -0
- jolt/pkgs/libglvnd.py +30 -0
- jolt/pkgs/libogg.py +28 -0
- jolt/pkgs/libpciaccess.py +18 -0
- jolt/pkgs/libseccomp.py +21 -0
- jolt/pkgs/libtirpc.py +24 -0
- jolt/pkgs/libtool.py +42 -0
- jolt/pkgs/libunwind.py +35 -0
- jolt/pkgs/libva.py +18 -0
- jolt/pkgs/libvorbis.py +33 -0
- jolt/pkgs/libxml2.py +35 -0
- jolt/pkgs/libxslt.py +17 -0
- jolt/pkgs/libyajl.py +16 -0
- jolt/pkgs/llvm.py +81 -0
- jolt/pkgs/lua.py +54 -0
- jolt/pkgs/lz4.py +26 -0
- jolt/pkgs/m4.py +14 -0
- jolt/pkgs/make.py +17 -0
- jolt/pkgs/mesa.py +81 -0
- jolt/pkgs/meson.py +17 -0
- jolt/pkgs/mstch.py +28 -0
- jolt/pkgs/mysql.py +60 -0
- jolt/pkgs/nasm.py +49 -0
- jolt/pkgs/ncurses.py +30 -0
- jolt/pkgs/ng_log.py +25 -0
- jolt/pkgs/ninja.py +45 -0
- jolt/pkgs/nlohmann_json.py +25 -0
- jolt/pkgs/nodejs.py +19 -11
- jolt/pkgs/opencv.py +24 -0
- jolt/pkgs/openjdk.py +26 -0
- jolt/pkgs/openssl.py +103 -0
- jolt/pkgs/paho.py +76 -0
- jolt/pkgs/patchelf.py +16 -0
- jolt/pkgs/perl.py +42 -0
- jolt/pkgs/pkgconfig.py +64 -0
- jolt/pkgs/poco.py +39 -0
- jolt/pkgs/protobuf.py +77 -0
- jolt/pkgs/pugixml.py +27 -0
- jolt/pkgs/python.py +19 -0
- jolt/pkgs/qt.py +35 -0
- jolt/pkgs/rapidjson.py +26 -0
- jolt/pkgs/rapidyaml.py +28 -0
- jolt/pkgs/re2.py +30 -0
- jolt/pkgs/re2c.py +17 -0
- jolt/pkgs/readline.py +15 -0
- jolt/pkgs/rust.py +41 -0
- jolt/pkgs/sdl.py +28 -0
- jolt/pkgs/simdjson.py +27 -0
- jolt/pkgs/soci.py +46 -0
- jolt/pkgs/spdlog.py +29 -0
- jolt/pkgs/spirv_llvm.py +21 -0
- jolt/pkgs/spirv_tools.py +24 -0
- jolt/pkgs/sqlite.py +83 -0
- jolt/pkgs/ssl.py +12 -0
- jolt/pkgs/texinfo.py +15 -0
- jolt/pkgs/tomlplusplus.py +22 -0
- jolt/pkgs/wayland.py +26 -0
- jolt/pkgs/x11.py +58 -0
- jolt/pkgs/xerces_c.py +20 -0
- jolt/pkgs/xorg.py +360 -0
- jolt/pkgs/xz.py +29 -0
- jolt/pkgs/yamlcpp.py +30 -0
- jolt/pkgs/zeromq.py +47 -0
- jolt/pkgs/zlib.py +69 -0
- jolt/pkgs/zstd.py +33 -0
- jolt/plugins/alias.py +3 -0
- jolt/plugins/allure.py +5 -2
- jolt/plugins/autotools.py +66 -0
- jolt/plugins/cache.py +133 -0
- jolt/plugins/cmake.py +74 -6
- jolt/plugins/conan.py +238 -0
- jolt/plugins/cxx.py +698 -0
- jolt/plugins/cxxinfo.py +7 -0
- jolt/plugins/dashboard.py +1 -1
- jolt/plugins/docker.py +91 -23
- jolt/plugins/email.py +5 -2
- jolt/plugins/email.xslt +144 -101
- jolt/plugins/environ.py +11 -0
- jolt/plugins/fetch.py +141 -0
- jolt/plugins/gdb.py +44 -21
- jolt/plugins/gerrit.py +1 -14
- jolt/plugins/git.py +316 -101
- jolt/plugins/googletest.py +522 -1
- jolt/plugins/http.py +36 -38
- jolt/plugins/libtool.py +63 -0
- jolt/plugins/linux.py +990 -0
- jolt/plugins/logstash.py +4 -4
- jolt/plugins/meson.py +61 -0
- jolt/plugins/ninja-compdb.py +107 -31
- jolt/plugins/ninja.py +929 -134
- jolt/plugins/paths.py +11 -1
- jolt/plugins/pkgconfig.py +219 -0
- jolt/plugins/podman.py +148 -91
- jolt/plugins/python.py +137 -0
- jolt/plugins/remote_execution/__init__.py +0 -0
- jolt/plugins/remote_execution/administration_pb2.py +46 -0
- jolt/plugins/remote_execution/administration_pb2_grpc.py +170 -0
- jolt/plugins/remote_execution/log_pb2.py +32 -0
- jolt/plugins/remote_execution/log_pb2_grpc.py +68 -0
- jolt/plugins/remote_execution/scheduler_pb2.py +41 -0
- jolt/plugins/remote_execution/scheduler_pb2_grpc.py +141 -0
- jolt/plugins/remote_execution/worker_pb2.py +38 -0
- jolt/plugins/remote_execution/worker_pb2_grpc.py +112 -0
- jolt/plugins/report.py +12 -2
- jolt/plugins/rust.py +25 -0
- jolt/plugins/scheduler.py +710 -0
- jolt/plugins/selfdeploy/setup.py +9 -4
- jolt/plugins/selfdeploy.py +138 -88
- jolt/plugins/strings.py +35 -22
- jolt/plugins/symlinks.py +26 -11
- jolt/plugins/telemetry.py +5 -2
- jolt/plugins/timeline.py +13 -3
- jolt/plugins/volume.py +46 -48
- jolt/scheduler.py +591 -191
- jolt/tasks.py +1783 -245
- jolt/templates/export.sh.template +12 -6
- jolt/templates/timeline.html.template +44 -47
- jolt/timer.py +22 -0
- jolt/tools.py +749 -302
- jolt/utils.py +245 -18
- jolt/version.py +1 -1
- jolt/version_utils.py +2 -2
- jolt/xmldom.py +12 -2
- {jolt-0.9.76.dist-info → jolt-0.9.429.dist-info}/METADATA +98 -38
- jolt-0.9.429.dist-info/RECORD +207 -0
- {jolt-0.9.76.dist-info → jolt-0.9.429.dist-info}/WHEEL +1 -1
- jolt/plugins/amqp.py +0 -834
- jolt/plugins/debian.py +0 -338
- jolt/plugins/ftp.py +0 -181
- jolt/plugins/ninja-cache.py +0 -64
- jolt/plugins/ninjacli.py +0 -271
- jolt/plugins/repo.py +0 -253
- jolt-0.9.76.dist-info/RECORD +0 -79
- {jolt-0.9.76.dist-info → jolt-0.9.429.dist-info}/entry_points.txt +0 -0
- {jolt-0.9.76.dist-info → jolt-0.9.429.dist-info}/top_level.txt +0 -0
jolt/plugins/googletest.py
CHANGED
|
@@ -1,7 +1,528 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This module provides the :class:`GTestRunner` task base class, a derivation
|
|
3
|
+
of :class:`jolt.tasks.Runner` for running Google Test applications.
|
|
4
|
+
Several parameters can be assigned or overidden to control the behavior.
|
|
5
|
+
|
|
6
|
+
Example:
|
|
7
|
+
|
|
8
|
+
.. literalinclude:: ../examples/googletest/runner.jolt
|
|
9
|
+
:language: python
|
|
10
|
+
:caption: examples/googletest/runner.jolt
|
|
11
|
+
|
|
12
|
+
The module also provides a set of task decorators for use with standalone
|
|
13
|
+
task classes. They set different ``GTEST_*`` environment variables to control
|
|
14
|
+
the behavior of Google Test executables in the same manner as the parameters in
|
|
15
|
+
:class:`GTestRunner` do.
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
Example:
|
|
19
|
+
|
|
20
|
+
.. code-block:: python
|
|
21
|
+
|
|
22
|
+
from jolt import Task
|
|
23
|
+
from jolt.plugins import googletest
|
|
24
|
+
|
|
25
|
+
# ....
|
|
26
|
+
|
|
27
|
+
@googletest.fail_fast(default=True)
|
|
28
|
+
@googletest.repeat(default=10)
|
|
29
|
+
@googletest.filter()
|
|
30
|
+
@googletest.junit_report()
|
|
31
|
+
class TestRunner(Task):
|
|
32
|
+
requires = ["test"]
|
|
33
|
+
|
|
34
|
+
def run(self, deps, tools):
|
|
35
|
+
tools.run("unittest")
|
|
36
|
+
|
|
37
|
+
.. code-block:: bash
|
|
38
|
+
|
|
39
|
+
$ jolt build testrunner:repeat=1,filter=TestModule.*
|
|
40
|
+
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
from functools import wraps
|
|
44
|
+
from os import path
|
|
45
|
+
import json
|
|
46
|
+
|
|
47
|
+
from jolt import BooleanParameter, IntParameter, Parameter, Runner
|
|
48
|
+
from jolt import influence
|
|
49
|
+
from jolt.error import raise_task_error, raise_task_error_if
|
|
1
50
|
from jolt.plugins import junit
|
|
2
|
-
from jolt.utils import deprecated
|
|
51
|
+
from jolt.utils import deprecated, ignore_exception
|
|
3
52
|
|
|
4
53
|
|
|
5
54
|
@deprecated
|
|
6
55
|
def import_failures(xml, report):
|
|
7
56
|
return junit.import_junit_report(xml, report, errors=True, failures=True)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def break_on_failure(default: bool = False, param: bool = True, attr: str = "break_on_failure"):
|
|
60
|
+
"""
|
|
61
|
+
Task class decorator controlling the GTEST_BREAK_ON_FAILURE environment variable.
|
|
62
|
+
|
|
63
|
+
When the variable is set, test applications failures trigger breakpoints. On Linux,
|
|
64
|
+
this typically results in a core dump that can be loaded into the debugger.
|
|
65
|
+
|
|
66
|
+
The value is taken from the parameter ``break_on_failure`` which is created
|
|
67
|
+
by default. If no parameter is created, the value is instead taken from the class
|
|
68
|
+
attribute with the same name. The name of the paramter/attribute can be changed.
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
default (boolean): Default value of the parameter and env. variable.
|
|
72
|
+
Default: False.
|
|
73
|
+
param (boolean): Create a task parameter. Default: True.
|
|
74
|
+
attr (str): Name of parameter or class attribute.
|
|
75
|
+
|
|
76
|
+
"""
|
|
77
|
+
|
|
78
|
+
def decorator(cls):
|
|
79
|
+
_old_run = cls.run
|
|
80
|
+
|
|
81
|
+
@wraps(cls.run)
|
|
82
|
+
def run(self, deps, tools):
|
|
83
|
+
with tools.environ(GTEST_BREAK_ON_FAILURE=str(int(bool(getattr(self, attr, default))))):
|
|
84
|
+
_old_run(self, deps, tools)
|
|
85
|
+
|
|
86
|
+
if param:
|
|
87
|
+
break_on_failure_param = BooleanParameter(default, help="Trigger breakpoint on failures.")
|
|
88
|
+
break_on_failure_param.__set_name__(cls, attr)
|
|
89
|
+
setattr(cls, attr, break_on_failure_param)
|
|
90
|
+
|
|
91
|
+
cls.run = run
|
|
92
|
+
return influence.source("googletest.break_on_failure", break_on_failure)(cls)
|
|
93
|
+
|
|
94
|
+
return decorator
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def brief(default: bool = False, param: bool = True, attr: str = "brief"):
|
|
98
|
+
"""
|
|
99
|
+
Task class decorator controlling the GTEST_BRIEF environment variable.
|
|
100
|
+
|
|
101
|
+
When the variable is set, only failed test-cases are logged.
|
|
102
|
+
|
|
103
|
+
The value is taken from the parameter ``brief`` which is created
|
|
104
|
+
by default. If no parameter is created, the value is instead taken from the class
|
|
105
|
+
attribute with the same name. The name of the paramter/attribute can be changed.
|
|
106
|
+
|
|
107
|
+
GoogleTest version >= 1.11 is required.
|
|
108
|
+
|
|
109
|
+
Args:
|
|
110
|
+
default (boolean): Default value of the parameter and env. variable.
|
|
111
|
+
Default: False.
|
|
112
|
+
param (boolean): Create a task parameter. Default: True.
|
|
113
|
+
attr (str): Name of parameter or class attribute.
|
|
114
|
+
|
|
115
|
+
"""
|
|
116
|
+
|
|
117
|
+
def decorator(cls):
|
|
118
|
+
_old_run = cls.run
|
|
119
|
+
|
|
120
|
+
@wraps(cls.run)
|
|
121
|
+
def run(self, deps, tools):
|
|
122
|
+
with tools.environ(GTEST_BRIEF=str(int(bool(getattr(self, attr, default))))):
|
|
123
|
+
_old_run(self, deps, tools)
|
|
124
|
+
|
|
125
|
+
if param:
|
|
126
|
+
brief_param = BooleanParameter(default, help="Only print failed test-cases.")
|
|
127
|
+
brief_param.__set_name__(cls, attr)
|
|
128
|
+
setattr(cls, attr, brief_param)
|
|
129
|
+
|
|
130
|
+
cls.run = run
|
|
131
|
+
return influence.source("googletest.brief", brief)(cls)
|
|
132
|
+
|
|
133
|
+
return decorator
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def disabled(default: bool = False, param: bool = True, attr: str = "disabled"):
|
|
137
|
+
"""
|
|
138
|
+
Task class decorator controlling the GTEST_ALSO_RUN_DISABLED_TESTS environment variable.
|
|
139
|
+
|
|
140
|
+
When the variable is set, disabled test-cases are also run.
|
|
141
|
+
|
|
142
|
+
The value is taken from the parameter ``disabled`` which is created
|
|
143
|
+
by default. If no parameter is created, the value is instead taken from the class
|
|
144
|
+
attribute with the same name. The name of the paramter/attribute can be changed.
|
|
145
|
+
|
|
146
|
+
Args:
|
|
147
|
+
default (boolean): Default value of the parameter and env. variable.
|
|
148
|
+
Default: False.
|
|
149
|
+
param (boolean): Create a task parameter. Default: True.
|
|
150
|
+
attr (str): Name of parameter or class attribute.
|
|
151
|
+
|
|
152
|
+
"""
|
|
153
|
+
|
|
154
|
+
def decorator(cls):
|
|
155
|
+
_old_run = cls.run
|
|
156
|
+
|
|
157
|
+
@wraps(cls.run)
|
|
158
|
+
def run(self, deps, tools):
|
|
159
|
+
with tools.environ(GTEST_ALSO_RUN_DISABLED_TESTS=str(int(bool(getattr(self, attr, default))))):
|
|
160
|
+
_old_run(self, deps, tools)
|
|
161
|
+
|
|
162
|
+
if param:
|
|
163
|
+
disabled_param = BooleanParameter(default, help="Also run disabled test-cases.")
|
|
164
|
+
disabled_param.__set_name__(cls, attr)
|
|
165
|
+
setattr(cls, attr, disabled_param)
|
|
166
|
+
|
|
167
|
+
cls.run = run
|
|
168
|
+
return influence.source("googletest.disabled", disabled)(cls)
|
|
169
|
+
|
|
170
|
+
return decorator
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def fail_fast(default: bool = False, param: bool = True, attr: str = "fail_fast"):
|
|
174
|
+
"""
|
|
175
|
+
Task class decorator controlling the GTEST_FAIL_FAST environment variable.
|
|
176
|
+
|
|
177
|
+
When the variable is set, test applications will abort when the first failure is found.
|
|
178
|
+
|
|
179
|
+
The value is taken from the parameter ``fail_fast`` which is created
|
|
180
|
+
by default. If no parameter is created, the value is instead taken from the class
|
|
181
|
+
attribute with the same name. The name of the paramter/attribute can be changed.
|
|
182
|
+
|
|
183
|
+
Args:
|
|
184
|
+
default (boolean): Default value of the parameter and env. variable.
|
|
185
|
+
Default: False.
|
|
186
|
+
param (boolean): Create a task parameter. Default: True.
|
|
187
|
+
attr (str): Name of parameter or class attribute.
|
|
188
|
+
|
|
189
|
+
"""
|
|
190
|
+
|
|
191
|
+
def decorator(cls):
|
|
192
|
+
_old_run = cls.run
|
|
193
|
+
|
|
194
|
+
@wraps(cls.run)
|
|
195
|
+
def run(self, deps, tools):
|
|
196
|
+
with tools.environ(GTEST_FAIL_FAST=str(int(bool(getattr(self, attr, default))))):
|
|
197
|
+
_old_run(self, deps, tools)
|
|
198
|
+
|
|
199
|
+
if param:
|
|
200
|
+
fail_fast_param = BooleanParameter(default, help="Stop when the first failure is found.")
|
|
201
|
+
fail_fast_param.__set_name__(cls, attr)
|
|
202
|
+
setattr(cls, attr, fail_fast_param)
|
|
203
|
+
|
|
204
|
+
cls.run = run
|
|
205
|
+
return influence.source("googletest.fail_fast", fail_fast)(cls)
|
|
206
|
+
|
|
207
|
+
return decorator
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
def filter(default: str = "*", param: bool = True, attr: str = "filter"):
|
|
211
|
+
"""
|
|
212
|
+
Task class decorator controlling the GTEST_FILTER environment variable.
|
|
213
|
+
|
|
214
|
+
The variable instructs test applications to only run test-cases that matches
|
|
215
|
+
a wildcard filter string (default: ``*``).
|
|
216
|
+
|
|
217
|
+
The value is taken from the parameter ``filter`` which is created
|
|
218
|
+
by default. If no parameter is created, the value is instead taken from the class
|
|
219
|
+
attribute with the same name. The name of the paramter/attribute can be changed.
|
|
220
|
+
|
|
221
|
+
Args:
|
|
222
|
+
default (boolean): Default value of the parameter and env. variable.
|
|
223
|
+
Default: False.
|
|
224
|
+
param (boolean): Create a task parameter. Default: True.
|
|
225
|
+
attr (str): Name of parameter or class attribute.
|
|
226
|
+
|
|
227
|
+
"""
|
|
228
|
+
|
|
229
|
+
def decorator(cls):
|
|
230
|
+
_old_run = cls.run
|
|
231
|
+
|
|
232
|
+
@wraps(cls.run)
|
|
233
|
+
def run(self, deps, tools):
|
|
234
|
+
with tools.environ(GTEST_FILTER=str(getattr(self, attr, default))):
|
|
235
|
+
_old_run(self, deps, tools)
|
|
236
|
+
|
|
237
|
+
if param:
|
|
238
|
+
filter_param = Parameter(default, help="Test-case filter")
|
|
239
|
+
filter_param.__set_name__(cls, attr)
|
|
240
|
+
setattr(cls, attr, filter_param)
|
|
241
|
+
|
|
242
|
+
cls.run = run
|
|
243
|
+
return influence.source("googletest.filter", filter)(cls)
|
|
244
|
+
|
|
245
|
+
return decorator
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
def junit_report():
|
|
249
|
+
"""
|
|
250
|
+
Decorator enabling JUnit test reporting in Google Test applications.
|
|
251
|
+
|
|
252
|
+
The decorator sets the GTEST_OUTPUT environment, thereby instructing
|
|
253
|
+
test applications to write a JUnit report file upon test completion.
|
|
254
|
+
The task publishes the report in the task artifact under report/junit/.
|
|
255
|
+
|
|
256
|
+
Any errors found in the report are parsed and attached to the task.
|
|
257
|
+
They are included in email reports if the email plugin is enabled.
|
|
258
|
+
"""
|
|
259
|
+
|
|
260
|
+
def decorator(cls):
|
|
261
|
+
_old_run = cls.run
|
|
262
|
+
_old_publish = cls.publish
|
|
263
|
+
|
|
264
|
+
@wraps(cls.run)
|
|
265
|
+
def run(self, deps, tools):
|
|
266
|
+
raise_task_error_if(
|
|
267
|
+
tools.getenv("GTEST_OUTPUT"),
|
|
268
|
+
self,
|
|
269
|
+
"GoogleTest output already enabled, cannot proceed with JUnit report setup")
|
|
270
|
+
gtestdir = tools.builddir("gtest-junit-report")
|
|
271
|
+
gtestreport = path.join(gtestdir, "report.xml")
|
|
272
|
+
with tools.environ(GTEST_OUTPUT="xml:" + gtestreport):
|
|
273
|
+
try:
|
|
274
|
+
_old_run(self, deps, tools)
|
|
275
|
+
finally:
|
|
276
|
+
with ignore_exception(), self.report() as report:
|
|
277
|
+
junit.import_junit_report(gtestreport, report)
|
|
278
|
+
|
|
279
|
+
@wraps(cls.publish)
|
|
280
|
+
def publish(self, artifact, tools):
|
|
281
|
+
_old_publish(self, artifact, tools)
|
|
282
|
+
gtestdir = tools.builddir("gtest-junit-report")
|
|
283
|
+
with tools.cwd(gtestdir):
|
|
284
|
+
artifact.collect("*", "report/junit/")
|
|
285
|
+
|
|
286
|
+
cls.run = run
|
|
287
|
+
cls.publish = publish
|
|
288
|
+
return influence.source("googletest.junit_report", junit_report)(cls)
|
|
289
|
+
|
|
290
|
+
return decorator
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
def json_report():
|
|
294
|
+
"""
|
|
295
|
+
Decorator enabling JSON test reporting in Google Test applications.
|
|
296
|
+
|
|
297
|
+
The decorator sets the GTEST_OUTPUT environment, thereby instructing
|
|
298
|
+
test applications to write a JSON report file upon test completion.
|
|
299
|
+
The task publishes the report in the task artifact under report/json/.
|
|
300
|
+
|
|
301
|
+
Any errors found in the report are parsed and attached to the task.
|
|
302
|
+
They are included in email reports if the email plugin is enabled.
|
|
303
|
+
"""
|
|
304
|
+
|
|
305
|
+
def decorator(cls):
|
|
306
|
+
_old_run = cls.run
|
|
307
|
+
_old_publish = cls.publish
|
|
308
|
+
|
|
309
|
+
@wraps(cls.run)
|
|
310
|
+
def run(self, deps, tools):
|
|
311
|
+
raise_task_error_if(
|
|
312
|
+
tools.getenv("GTEST_OUTPUT"),
|
|
313
|
+
self,
|
|
314
|
+
"GoogleTest output already enabled, cannot proceed with JSON report setup")
|
|
315
|
+
gtestdir = tools.builddir("gtest-json-report")
|
|
316
|
+
gtestreport = path.join(gtestdir, "report.json")
|
|
317
|
+
with tools.environ(GTEST_OUTPUT="json:" + gtestreport):
|
|
318
|
+
try:
|
|
319
|
+
_old_run(self, deps, tools)
|
|
320
|
+
finally:
|
|
321
|
+
with ignore_exception(), self.report() as report:
|
|
322
|
+
with open(gtestreport) as fp:
|
|
323
|
+
json_report = json.load(fp)
|
|
324
|
+
for testsuite in json_report["testsuites"]:
|
|
325
|
+
for testcase in testsuite["testsuite"]:
|
|
326
|
+
failures = testcase.get("failures", [])
|
|
327
|
+
for failure in failures:
|
|
328
|
+
name = f"{testsuite['name']}.{testcase['name']}"
|
|
329
|
+
message = failure["failure"]
|
|
330
|
+
report.add_error("Test Failed", name, message)
|
|
331
|
+
|
|
332
|
+
@wraps(cls.publish)
|
|
333
|
+
def publish(self, artifact, tools):
|
|
334
|
+
_old_publish(self, artifact, tools)
|
|
335
|
+
gtestdir = tools.builddir("gtest-json-report")
|
|
336
|
+
with tools.cwd(gtestdir):
|
|
337
|
+
artifact.collect("*", "report/json/")
|
|
338
|
+
|
|
339
|
+
cls.run = run
|
|
340
|
+
cls.publish = publish
|
|
341
|
+
return influence.source("googletest.json_report", json_report)(cls)
|
|
342
|
+
|
|
343
|
+
return decorator
|
|
344
|
+
|
|
345
|
+
|
|
346
|
+
def repeat(default: int = 1, param: bool = True, attr: str = "repeat"):
|
|
347
|
+
"""
|
|
348
|
+
Task class decorator controlling the GTEST_REPEAT environment variable.
|
|
349
|
+
|
|
350
|
+
The variable instructs test applications to repeat test-cases the specified
|
|
351
|
+
number of times.
|
|
352
|
+
|
|
353
|
+
The value is taken from the parameter ``repeat`` which is created
|
|
354
|
+
by default. If no parameter is created, the value is instead taken from the class
|
|
355
|
+
attribute with the same name. The name of the paramter/attribute can be changed.
|
|
356
|
+
|
|
357
|
+
Args:
|
|
358
|
+
default (boolean): Default value of the parameter and env. variable.
|
|
359
|
+
Default: False.
|
|
360
|
+
param (boolean): Create a task parameter. Default: True.
|
|
361
|
+
attr (str): Name of parameter or class attribute.
|
|
362
|
+
|
|
363
|
+
"""
|
|
364
|
+
|
|
365
|
+
def decorator(cls):
|
|
366
|
+
_old_run = cls.run
|
|
367
|
+
|
|
368
|
+
@wraps(cls.run)
|
|
369
|
+
def run(self, deps, tools):
|
|
370
|
+
try:
|
|
371
|
+
repeat = int(getattr(self, attr, default))
|
|
372
|
+
except ValueError:
|
|
373
|
+
raise_task_error(self, f"Value assigned to '{attr}' is not an integer")
|
|
374
|
+
with tools.environ(GTEST_REPEAT=str(repeat)):
|
|
375
|
+
_old_run(self, deps, tools)
|
|
376
|
+
|
|
377
|
+
if param:
|
|
378
|
+
repeat_param = IntParameter(default, help="Test-case repetitions.")
|
|
379
|
+
repeat_param.__set_name__(cls, attr)
|
|
380
|
+
setattr(cls, attr, repeat_param)
|
|
381
|
+
|
|
382
|
+
cls.run = run
|
|
383
|
+
return influence.source("googletest.repeat", repeat)(cls)
|
|
384
|
+
|
|
385
|
+
return decorator
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
def seed(default: int = 0, param: bool = True, attr: str = "seed"):
|
|
389
|
+
"""
|
|
390
|
+
Task class decorator controlling the GTEST_RANDOM_SEED environment variable.
|
|
391
|
+
|
|
392
|
+
The variable sets an initial value for the random number generator used to
|
|
393
|
+
shuffle test-cases. In order to reproduce ordering issues, a user may assign
|
|
394
|
+
a specific seed to get the same test-case order. The default value is 0
|
|
395
|
+
which causes Google Test to use time as the seed.
|
|
396
|
+
|
|
397
|
+
The value is taken from the parameter ``seed`` which is created
|
|
398
|
+
by default. If no parameter is created, the value is instead taken from the class
|
|
399
|
+
attribute with the same name. The name of the paramter/attribute can be changed.
|
|
400
|
+
|
|
401
|
+
Args:
|
|
402
|
+
default (boolean): Default value of the parameter and env. variable.
|
|
403
|
+
Default: False.
|
|
404
|
+
param (boolean): Create a task parameter. Default: True.
|
|
405
|
+
attr (str): Name of parameter or class attribute.
|
|
406
|
+
|
|
407
|
+
"""
|
|
408
|
+
|
|
409
|
+
def decorator(cls):
|
|
410
|
+
_old_run = cls.run
|
|
411
|
+
|
|
412
|
+
@wraps(cls.run)
|
|
413
|
+
def run(self, deps, tools):
|
|
414
|
+
try:
|
|
415
|
+
seed = int(getattr(self, attr, default))
|
|
416
|
+
except ValueError:
|
|
417
|
+
raise_task_error(self, f"Value assigned to '{attr}' is not an integer")
|
|
418
|
+
with tools.environ(GTEST_RANDOM_SEED=str(seed)):
|
|
419
|
+
_old_run(self, deps, tools)
|
|
420
|
+
|
|
421
|
+
if param:
|
|
422
|
+
seed_param = IntParameter(default, min=0, max=99999, help="Random number generator seed.")
|
|
423
|
+
seed_param.__set_name__(cls, attr)
|
|
424
|
+
setattr(cls, attr, seed_param)
|
|
425
|
+
|
|
426
|
+
cls.run = run
|
|
427
|
+
return influence.source("googletest.seed", seed)(cls)
|
|
428
|
+
|
|
429
|
+
return decorator
|
|
430
|
+
|
|
431
|
+
|
|
432
|
+
def shuffle(default: bool = False, param: bool = True, attr: str = "shuffle"):
|
|
433
|
+
"""
|
|
434
|
+
Task class decorator controlling the GTEST_SHUFFLE environment variable.
|
|
435
|
+
|
|
436
|
+
When set, the test application runs its test-cases in random order.
|
|
437
|
+
In order to reproduce test-case ordering issues, a user may assign a specific
|
|
438
|
+
random number generator seed to get the same test-case execution order.
|
|
439
|
+
See :func:`seed`.
|
|
440
|
+
|
|
441
|
+
The value is taken from the parameter ``shuffle`` which is created
|
|
442
|
+
by default. If no parameter is created, the value is instead taken from the class
|
|
443
|
+
attribute with the same name. The name of the paramter/attribute can be changed.
|
|
444
|
+
|
|
445
|
+
Args:
|
|
446
|
+
default (boolean): Default value of the parameter and env. variable.
|
|
447
|
+
Default: False.
|
|
448
|
+
param (boolean): Create a task parameter. Default: True.
|
|
449
|
+
attr (str): Name of parameter or class attribute.
|
|
450
|
+
|
|
451
|
+
"""
|
|
452
|
+
|
|
453
|
+
def decorator(cls):
|
|
454
|
+
_old_run = cls.run
|
|
455
|
+
|
|
456
|
+
@wraps(cls.run)
|
|
457
|
+
def run(self, deps, tools):
|
|
458
|
+
with tools.environ(GTEST_SHUFFLE=str(int(bool(getattr(self, attr, default))))):
|
|
459
|
+
_old_run(self, deps, tools)
|
|
460
|
+
|
|
461
|
+
if param:
|
|
462
|
+
shuffle_param = BooleanParameter(default, help="Randomize test-case execution order.")
|
|
463
|
+
shuffle_param.__set_name__(cls, attr)
|
|
464
|
+
setattr(cls, attr, shuffle_param)
|
|
465
|
+
|
|
466
|
+
cls.run = run
|
|
467
|
+
return influence.source("googletest.shuffle", shuffle)(cls)
|
|
468
|
+
|
|
469
|
+
return decorator
|
|
470
|
+
|
|
471
|
+
|
|
472
|
+
@break_on_failure()
|
|
473
|
+
@brief()
|
|
474
|
+
@disabled()
|
|
475
|
+
@fail_fast()
|
|
476
|
+
@filter()
|
|
477
|
+
@junit_report()
|
|
478
|
+
@repeat()
|
|
479
|
+
@seed()
|
|
480
|
+
@shuffle()
|
|
481
|
+
class GTestRunner(Runner):
|
|
482
|
+
"""
|
|
483
|
+
Abstract task base class that runs Google Test applications.
|
|
484
|
+
|
|
485
|
+
Test executables are consumed from requirement artifacts. The
|
|
486
|
+
artifacts must export metadata indicating the name of the binary,
|
|
487
|
+
using ``artifact.strings.executable``.
|
|
488
|
+
|
|
489
|
+
A number of parameters can be assigned from the command line
|
|
490
|
+
to control the behavior of the task. Parameters can also be
|
|
491
|
+
overridden using regular Python class attributes in subclasses.
|
|
492
|
+
|
|
493
|
+
A JUnit test report is generated and published in the task artifact.
|
|
494
|
+
The results of the report are also imported into Jolt and distributed
|
|
495
|
+
with report emails if the email plugin has been enabled.
|
|
496
|
+
|
|
497
|
+
Example:
|
|
498
|
+
|
|
499
|
+
.. literalinclude:: ../examples/googletest/runner.jolt
|
|
500
|
+
:language: python
|
|
501
|
+
:caption: examples/googletest/runner.jolt
|
|
502
|
+
"""
|
|
503
|
+
|
|
504
|
+
abstract = True
|
|
505
|
+
|
|
506
|
+
break_on_failure = BooleanParameter(False, help="Trigger breakpoint on failures.")
|
|
507
|
+
""" Trigger breakpoint on test-case failure. """
|
|
508
|
+
|
|
509
|
+
brief = BooleanParameter(False, help="Only print failed test-cases.")
|
|
510
|
+
""" Only print failed test-cases. """
|
|
511
|
+
|
|
512
|
+
disabled = BooleanParameter(False, help="Also run disabled test-cases.")
|
|
513
|
+
""" Also run disabled test-cases. """
|
|
514
|
+
|
|
515
|
+
fail_fast = BooleanParameter(False, help="Stop when the first failure is found.")
|
|
516
|
+
""" Stop when the first failure is found. """
|
|
517
|
+
|
|
518
|
+
filter = Parameter("*", help="Test-case filter.")
|
|
519
|
+
""" Test-case filter. """
|
|
520
|
+
|
|
521
|
+
repeat = IntParameter(1, help="Test-case repetitions.")
|
|
522
|
+
""" Test-case repetitions. """
|
|
523
|
+
|
|
524
|
+
seed = IntParameter(0, min=0, max=99999, help="Random number generator seed.")
|
|
525
|
+
""" Random number generator seed. """
|
|
526
|
+
|
|
527
|
+
shuffle = BooleanParameter(True, help="Randomize test-case execution order.")
|
|
528
|
+
""" Randomize test-case execution order. """
|
jolt/plugins/http.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from requests.auth import HTTPBasicAuth
|
|
2
2
|
from requests.exceptions import ConnectTimeout, RequestException
|
|
3
|
+
from urllib.parse import urlparse, urlunparse
|
|
3
4
|
import keyring
|
|
4
5
|
import getpass
|
|
5
6
|
|
|
@@ -9,6 +10,7 @@ from jolt import cache
|
|
|
9
10
|
from jolt import log
|
|
10
11
|
from jolt import config
|
|
11
12
|
from jolt import filesystem as fs
|
|
13
|
+
from jolt import tools
|
|
12
14
|
from jolt.error import raise_error_if, JoltError
|
|
13
15
|
|
|
14
16
|
|
|
@@ -21,10 +23,9 @@ class Http(cache.StorageProvider):
|
|
|
21
23
|
def __init__(self, cache):
|
|
22
24
|
super(Http, self).__init__()
|
|
23
25
|
self._cache = cache
|
|
24
|
-
self._uri = config.get(NAME, "uri")
|
|
26
|
+
self._uri = config.get(NAME, "uri", "http://cache")
|
|
27
|
+
self._uri = self._uri.rstrip("/")
|
|
25
28
|
raise_error_if(not self._uri, "HTTP URI not configured")
|
|
26
|
-
if self._uri[-1] != "/":
|
|
27
|
-
self._uri += "/"
|
|
28
29
|
self._upload = config.getboolean(NAME, "upload", True)
|
|
29
30
|
self._download = config.getboolean(NAME, "download", True)
|
|
30
31
|
self._disabled = False
|
|
@@ -49,65 +50,62 @@ class Http(cache.StorageProvider):
|
|
|
49
50
|
|
|
50
51
|
return HTTPBasicAuth(username, password)
|
|
51
52
|
|
|
52
|
-
def _get_url(self,
|
|
53
|
-
return
|
|
53
|
+
def _get_url(self, artifact):
|
|
54
|
+
return artifact.tools.expand(
|
|
55
|
+
"{uri}/{name}/{file}",
|
|
54
56
|
uri=self._uri,
|
|
55
|
-
name=
|
|
57
|
+
name=artifact.task.name,
|
|
56
58
|
file=fs.path.basename(artifact.get_archive_path()))
|
|
57
59
|
|
|
58
60
|
@utils.retried.on_exception((RequestException, JoltError))
|
|
59
|
-
def download(self,
|
|
61
|
+
def download(self, artifact, force=False):
|
|
60
62
|
if self._disabled:
|
|
61
63
|
return False
|
|
62
64
|
if not self._download and not force:
|
|
63
65
|
return False
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
66
|
+
url = self._get_url(artifact)
|
|
67
|
+
return artifact.tools.download(
|
|
68
|
+
url,
|
|
69
|
+
artifact.get_archive_path(),
|
|
70
|
+
exceptions=False,
|
|
71
|
+
timeout=TIMEOUT)
|
|
69
72
|
|
|
70
73
|
def download_enabled(self):
|
|
71
74
|
return not self._disabled and self._download
|
|
72
75
|
|
|
73
76
|
@utils.retried.on_exception((RequestException))
|
|
74
|
-
def upload(self,
|
|
77
|
+
def upload(self, artifact, force=False):
|
|
75
78
|
if self._disabled:
|
|
76
79
|
return True
|
|
77
80
|
if not self._upload and not force:
|
|
78
81
|
return True
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
timeout=TIMEOUT)
|
|
87
|
-
return False
|
|
82
|
+
url = self._get_url(artifact)
|
|
83
|
+
archive = artifact.get_archive()
|
|
84
|
+
return artifact.tools.upload(
|
|
85
|
+
archive, url,
|
|
86
|
+
exceptions=False,
|
|
87
|
+
auth=self._get_auth(),
|
|
88
|
+
timeout=TIMEOUT)
|
|
88
89
|
|
|
89
90
|
def upload_enabled(self):
|
|
90
91
|
return not self._disabled and self._upload
|
|
91
92
|
|
|
92
93
|
@utils.retried.on_exception((RequestException))
|
|
93
|
-
def location(self,
|
|
94
|
+
def location(self, artifact):
|
|
94
95
|
if self._disabled:
|
|
95
96
|
return False
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
url = self.
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
log.debug("[HTTP] Response: {0}", response.status_code)
|
|
109
|
-
return url if response.status_code == 200 else ''
|
|
110
|
-
return False
|
|
97
|
+
|
|
98
|
+
url = self._get_url(artifact)
|
|
99
|
+
try:
|
|
100
|
+
response = tools.http_session.head(url, stream=True, timeout=TIMEOUT_HEAD, auth=self._get_auth())
|
|
101
|
+
except ConnectTimeout:
|
|
102
|
+
self._disabled = True
|
|
103
|
+
log.warning("[HTTP] failed to establish server connection, disabled")
|
|
104
|
+
return False
|
|
105
|
+
|
|
106
|
+
log.debug("[HTTP] Head ({}): {}", response.status_code, url)
|
|
107
|
+
url = urlunparse(urlparse(url))
|
|
108
|
+
return url if response.status_code == 200 else ''
|
|
111
109
|
|
|
112
110
|
|
|
113
111
|
@cache.RegisterStorage
|