warp-lang 1.0.0b5__py3-none-manylinux2014_x86_64.whl → 1.0.0b6__py3-none-manylinux2014_x86_64.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.
- docs/conf.py +3 -4
- examples/env/env_ant.py +1 -1
- examples/env/env_cartpole.py +1 -1
- examples/env/env_humanoid.py +1 -1
- examples/example_dem.py +28 -26
- examples/example_diffray.py +37 -30
- examples/example_fluid.py +7 -3
- examples/example_jacobian_ik.py +1 -1
- examples/example_mesh_intersect.py +10 -7
- examples/example_nvdb.py +3 -3
- examples/example_render_opengl.py +19 -10
- examples/example_sim_cartpole.py +9 -5
- examples/example_sim_cloth.py +29 -25
- examples/example_sim_fk_grad.py +2 -2
- examples/example_sim_fk_grad_torch.py +3 -3
- examples/example_sim_grad_bounce.py +11 -8
- examples/example_sim_grad_cloth.py +12 -9
- examples/example_sim_granular.py +2 -2
- examples/example_sim_granular_collision_sdf.py +13 -13
- examples/example_sim_neo_hookean.py +3 -3
- examples/example_sim_particle_chain.py +2 -2
- examples/example_sim_quadruped.py +8 -5
- examples/example_sim_rigid_chain.py +8 -5
- examples/example_sim_rigid_contact.py +13 -10
- examples/example_sim_rigid_fem.py +2 -2
- examples/example_sim_rigid_gyroscopic.py +2 -2
- examples/example_sim_rigid_kinematics.py +1 -1
- examples/example_sim_trajopt.py +3 -2
- examples/fem/example_apic_fluid.py +5 -7
- examples/fem/example_diffusion_mgpu.py +18 -16
- warp/__init__.py +3 -2
- warp/bin/warp.so +0 -0
- warp/build_dll.py +29 -9
- warp/builtins.py +206 -7
- warp/codegen.py +58 -38
- warp/config.py +3 -1
- warp/context.py +234 -128
- warp/fem/__init__.py +2 -2
- warp/fem/cache.py +2 -1
- warp/fem/field/nodal_field.py +18 -17
- warp/fem/geometry/hexmesh.py +11 -6
- warp/fem/geometry/quadmesh_2d.py +16 -12
- warp/fem/geometry/tetmesh.py +19 -8
- warp/fem/geometry/trimesh_2d.py +18 -7
- warp/fem/integrate.py +341 -196
- warp/fem/quadrature/__init__.py +1 -1
- warp/fem/quadrature/pic_quadrature.py +138 -53
- warp/fem/quadrature/quadrature.py +81 -9
- warp/fem/space/__init__.py +1 -1
- warp/fem/space/basis_space.py +169 -51
- warp/fem/space/grid_2d_function_space.py +2 -2
- warp/fem/space/grid_3d_function_space.py +2 -2
- warp/fem/space/hexmesh_function_space.py +2 -2
- warp/fem/space/partition.py +9 -6
- warp/fem/space/quadmesh_2d_function_space.py +2 -2
- warp/fem/space/shape/cube_shape_function.py +27 -15
- warp/fem/space/shape/square_shape_function.py +29 -18
- warp/fem/space/tetmesh_function_space.py +2 -2
- warp/fem/space/topology.py +10 -0
- warp/fem/space/trimesh_2d_function_space.py +2 -2
- warp/fem/utils.py +10 -5
- warp/native/array.h +49 -8
- warp/native/builtin.h +31 -14
- warp/native/cuda_util.cpp +8 -3
- warp/native/cuda_util.h +1 -0
- warp/native/exports.h +1177 -1108
- warp/native/intersect.h +4 -4
- warp/native/intersect_adj.h +8 -8
- warp/native/mat.h +65 -6
- warp/native/mesh.h +126 -5
- warp/native/quat.h +28 -4
- warp/native/vec.h +76 -14
- warp/native/warp.cu +1 -6
- warp/render/render_opengl.py +261 -109
- warp/sim/import_mjcf.py +13 -7
- warp/sim/import_urdf.py +14 -14
- warp/sim/inertia.py +17 -18
- warp/sim/model.py +67 -67
- warp/sim/render.py +1 -1
- warp/sparse.py +6 -6
- warp/stubs.py +19 -81
- warp/tape.py +1 -1
- warp/tests/__main__.py +3 -6
- warp/tests/{test_class_kernel.py → aux_test_class_kernel.py} +9 -1
- warp/tests/aux_test_conditional_unequal_types_kernels.py +21 -0
- warp/tests/{test_dependent.py → aux_test_dependent.py} +2 -2
- warp/tests/{test_reference.py → aux_test_reference.py} +1 -1
- warp/tests/aux_test_unresolved_func.py +14 -0
- warp/tests/aux_test_unresolved_symbol.py +14 -0
- warp/tests/{test_kinematics.py → disabled_kinematics.py} +10 -12
- warp/tests/run_coverage_serial.py +31 -0
- warp/tests/test_adam.py +102 -106
- warp/tests/test_arithmetic.py +39 -40
- warp/tests/test_array.py +46 -48
- warp/tests/test_array_reduce.py +25 -19
- warp/tests/test_atomic.py +62 -26
- warp/tests/test_bool.py +16 -11
- warp/tests/test_builtins_resolution.py +1292 -0
- warp/tests/test_bvh.py +9 -12
- warp/tests/test_closest_point_edge_edge.py +53 -57
- warp/tests/test_codegen.py +164 -134
- warp/tests/test_compile_consts.py +13 -19
- warp/tests/test_conditional.py +30 -32
- warp/tests/test_copy.py +9 -12
- warp/tests/test_ctypes.py +90 -98
- warp/tests/test_dense.py +20 -14
- warp/tests/test_devices.py +34 -35
- warp/tests/test_dlpack.py +74 -75
- warp/tests/test_examples.py +215 -97
- warp/tests/test_fabricarray.py +15 -21
- warp/tests/test_fast_math.py +14 -11
- warp/tests/test_fem.py +280 -97
- warp/tests/test_fp16.py +19 -15
- warp/tests/test_func.py +177 -194
- warp/tests/test_generics.py +71 -77
- warp/tests/test_grad.py +83 -32
- warp/tests/test_grad_customs.py +7 -9
- warp/tests/test_hash_grid.py +6 -10
- warp/tests/test_import.py +9 -23
- warp/tests/test_indexedarray.py +19 -21
- warp/tests/test_intersect.py +15 -9
- warp/tests/test_large.py +17 -19
- warp/tests/test_launch.py +14 -17
- warp/tests/test_lerp.py +63 -63
- warp/tests/test_lvalue.py +84 -35
- warp/tests/test_marching_cubes.py +9 -13
- warp/tests/test_mat.py +388 -3004
- warp/tests/test_mat_lite.py +9 -12
- warp/tests/test_mat_scalar_ops.py +2889 -0
- warp/tests/test_math.py +10 -11
- warp/tests/test_matmul.py +104 -100
- warp/tests/test_matmul_lite.py +72 -98
- warp/tests/test_mesh.py +35 -32
- warp/tests/test_mesh_query_aabb.py +18 -25
- warp/tests/test_mesh_query_point.py +39 -23
- warp/tests/test_mesh_query_ray.py +9 -21
- warp/tests/test_mlp.py +8 -9
- warp/tests/test_model.py +89 -93
- warp/tests/test_modules_lite.py +15 -25
- warp/tests/test_multigpu.py +87 -114
- warp/tests/test_noise.py +10 -12
- warp/tests/test_operators.py +14 -21
- warp/tests/test_options.py +10 -11
- warp/tests/test_pinned.py +16 -18
- warp/tests/test_print.py +16 -20
- warp/tests/test_quat.py +121 -88
- warp/tests/test_rand.py +12 -13
- warp/tests/test_reload.py +27 -32
- warp/tests/test_rounding.py +7 -10
- warp/tests/test_runlength_encode.py +105 -106
- warp/tests/test_smoothstep.py +8 -9
- warp/tests/test_snippet.py +13 -22
- warp/tests/test_sparse.py +30 -29
- warp/tests/test_spatial.py +179 -174
- warp/tests/test_streams.py +100 -107
- warp/tests/test_struct.py +98 -67
- warp/tests/test_tape.py +11 -17
- warp/tests/test_torch.py +89 -86
- warp/tests/test_transient_module.py +9 -12
- warp/tests/test_types.py +328 -50
- warp/tests/test_utils.py +217 -218
- warp/tests/test_vec.py +133 -2133
- warp/tests/test_vec_lite.py +8 -11
- warp/tests/test_vec_scalar_ops.py +2099 -0
- warp/tests/test_volume.py +391 -382
- warp/tests/test_volume_write.py +122 -135
- warp/tests/unittest_serial.py +35 -0
- warp/tests/unittest_suites.py +291 -0
- warp/tests/{test_base.py → unittest_utils.py} +138 -25
- warp/tests/{test_misc.py → unused_test_misc.py} +13 -5
- warp/tests/{test_debug.py → walkthough_debug.py} +2 -15
- warp/thirdparty/unittest_parallel.py +257 -54
- warp/types.py +119 -98
- warp/utils.py +14 -0
- {warp_lang-1.0.0b5.dist-info → warp_lang-1.0.0b6.dist-info}/METADATA +2 -1
- {warp_lang-1.0.0b5.dist-info → warp_lang-1.0.0b6.dist-info}/RECORD +182 -178
- {warp_lang-1.0.0b5.dist-info → warp_lang-1.0.0b6.dist-info}/WHEEL +1 -1
- warp/tests/test_all.py +0 -239
- warp/tests/test_conditional_unequal_types_kernels.py +0 -14
- warp/tests/test_coverage.py +0 -38
- warp/tests/test_unresolved_func.py +0 -7
- warp/tests/test_unresolved_symbol.py +0 -7
- /warp/tests/{test_compile_consts_dummy.py → aux_test_compile_consts_dummy.py} +0 -0
- /warp/tests/{test_reference_reference.py → aux_test_reference_reference.py} +0 -0
- /warp/tests/{test_square.py → aux_test_square.py} +0 -0
- {warp_lang-1.0.0b5.dist-info → warp_lang-1.0.0b6.dist-info}/LICENSE.md +0 -0
- {warp_lang-1.0.0b5.dist-info → warp_lang-1.0.0b6.dist-info}/top_level.txt +0 -0
|
@@ -1,11 +1,22 @@
|
|
|
1
1
|
# Licensed under the MIT License
|
|
2
2
|
# https://github.com/craigahobbs/unittest-parallel/blob/main/LICENSE
|
|
3
3
|
|
|
4
|
+
# SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
5
|
+
# SPDX-License-Identifier: LicenseRef-NvidiaProprietary
|
|
6
|
+
#
|
|
7
|
+
# NVIDIA CORPORATION, its affiliates and licensors retain all intellectual
|
|
8
|
+
# property and proprietary rights in and to this material, related
|
|
9
|
+
# documentation and any modifications thereto. Any use, reproduction,
|
|
10
|
+
# disclosure or distribution of this material and related documentation
|
|
11
|
+
# without an express license agreement from NVIDIA CORPORATION or
|
|
12
|
+
# its affiliates is strictly prohibited.
|
|
13
|
+
|
|
4
14
|
"""
|
|
5
15
|
unittest-parallel command-line script main module
|
|
6
16
|
"""
|
|
7
17
|
|
|
8
18
|
import argparse
|
|
19
|
+
import concurrent.futures # NVIDIA Modification
|
|
9
20
|
import multiprocessing
|
|
10
21
|
import os
|
|
11
22
|
import sys
|
|
@@ -15,7 +26,20 @@ import unittest
|
|
|
15
26
|
from contextlib import contextmanager
|
|
16
27
|
from io import StringIO
|
|
17
28
|
|
|
18
|
-
import
|
|
29
|
+
import warp.tests.unittest_suites # NVIDIA Modification
|
|
30
|
+
|
|
31
|
+
try:
|
|
32
|
+
import coverage
|
|
33
|
+
|
|
34
|
+
COVERAGE_AVAILABLE = True # NVIDIA Modification
|
|
35
|
+
except ImportError:
|
|
36
|
+
COVERAGE_AVAILABLE = False # NVIDIA Modification
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
# The following variables are NVIDIA Modifications
|
|
40
|
+
RUNNING_IN_TEAMCITY = os.environ.get("TEAMCITY_VERSION") is not None
|
|
41
|
+
TEST_SUITE_NAME = "WarpTests"
|
|
42
|
+
START_DIRECTORY = os.path.dirname(__file__) # The directory to start test discovery
|
|
19
43
|
|
|
20
44
|
|
|
21
45
|
def main(argv=None):
|
|
@@ -25,8 +49,8 @@ def main(argv=None):
|
|
|
25
49
|
|
|
26
50
|
# Command line arguments
|
|
27
51
|
parser = argparse.ArgumentParser(prog="unittest-parallel")
|
|
28
|
-
parser.add_argument("-v", "--verbose", action="store_const", const=2, default=1, help="Verbose output")
|
|
29
|
-
parser.add_argument("-q", "--quiet", dest="verbose", action="store_const", const=0, default=
|
|
52
|
+
# parser.add_argument("-v", "--verbose", action="store_const", const=2, default=1, help="Verbose output")
|
|
53
|
+
parser.add_argument("-q", "--quiet", dest="verbose", action="store_const", const=0, default=2, help="Quiet output")
|
|
30
54
|
parser.add_argument("-f", "--failfast", action="store_true", default=False, help="Stop on first fail or error")
|
|
31
55
|
parser.add_argument(
|
|
32
56
|
"-b", "--buffer", action="store_true", default=False, help="Buffer stdout and stderr during tests"
|
|
@@ -38,9 +62,6 @@ def main(argv=None):
|
|
|
38
62
|
type=_convert_select_pattern,
|
|
39
63
|
help="Only run tests which match the given substring",
|
|
40
64
|
)
|
|
41
|
-
parser.add_argument(
|
|
42
|
-
"-s", "--start-directory", metavar="START", default=".", help="Directory to start discovery ('.' default)"
|
|
43
|
-
)
|
|
44
65
|
parser.add_argument(
|
|
45
66
|
"-p", "--pattern", metavar="PATTERN", default="test*.py", help="Pattern to match tests ('test*.py' default)"
|
|
46
67
|
)
|
|
@@ -59,11 +80,19 @@ def main(argv=None):
|
|
|
59
80
|
default=0,
|
|
60
81
|
help="The number of test processes (default is 0, all cores)",
|
|
61
82
|
)
|
|
83
|
+
group_parallel.add_argument(
|
|
84
|
+
"-m",
|
|
85
|
+
"--maxjobs",
|
|
86
|
+
metavar="MAXCOUNT",
|
|
87
|
+
type=int,
|
|
88
|
+
default=8,
|
|
89
|
+
help="The maximum number of test processes (default is 8)",
|
|
90
|
+
) # NVIDIA Modification
|
|
62
91
|
group_parallel.add_argument(
|
|
63
92
|
"--level",
|
|
64
93
|
choices=["module", "class", "test"],
|
|
65
|
-
default="
|
|
66
|
-
help="Set the test parallelism level (default is '
|
|
94
|
+
default="class",
|
|
95
|
+
help="Set the test parallelism level (default is 'class')",
|
|
67
96
|
)
|
|
68
97
|
group_parallel.add_argument(
|
|
69
98
|
"--disable-process-pooling",
|
|
@@ -71,40 +100,45 @@ def main(argv=None):
|
|
|
71
100
|
default=False,
|
|
72
101
|
help="Do not reuse processes used to run test suites",
|
|
73
102
|
)
|
|
103
|
+
group_parallel.add_argument(
|
|
104
|
+
"--disable-concurrent-futures",
|
|
105
|
+
action="store_true",
|
|
106
|
+
default=False,
|
|
107
|
+
help="Use multiprocessing instead of concurrent.futures.",
|
|
108
|
+
) # NVIDIA Modification
|
|
109
|
+
group_parallel.add_argument(
|
|
110
|
+
"--serial-fallback",
|
|
111
|
+
action="store_true",
|
|
112
|
+
default=False,
|
|
113
|
+
help="Run in a single-process (no spawning) mode without multiprocessing or concurrent.futures.",
|
|
114
|
+
) # NVIDIA Modification
|
|
74
115
|
group_coverage = parser.add_argument_group("coverage options")
|
|
75
116
|
group_coverage.add_argument("--coverage", action="store_true", help="Run tests with coverage")
|
|
76
117
|
group_coverage.add_argument("--coverage-branch", action="store_true", help="Run tests with branch coverage")
|
|
77
|
-
group_coverage.add_argument("--coverage-rcfile", metavar="RCFILE", help="Specify coverage configuration file")
|
|
78
|
-
group_coverage.add_argument(
|
|
79
|
-
"--coverage-include",
|
|
80
|
-
metavar="PAT",
|
|
81
|
-
action="append",
|
|
82
|
-
help="Include only files matching one of these patterns. Accepts shell-style (quoted) wildcards.",
|
|
83
|
-
)
|
|
84
|
-
group_coverage.add_argument(
|
|
85
|
-
"--coverage-omit",
|
|
86
|
-
metavar="PAT",
|
|
87
|
-
action="append",
|
|
88
|
-
help="Omit files matching one of these patterns. Accepts shell-style (quoted) wildcards.",
|
|
89
|
-
)
|
|
90
118
|
group_coverage.add_argument(
|
|
91
|
-
"--coverage-
|
|
92
|
-
metavar="
|
|
93
|
-
|
|
94
|
-
|
|
119
|
+
"--coverage-html",
|
|
120
|
+
metavar="DIR",
|
|
121
|
+
help="Generate coverage HTML report",
|
|
122
|
+
default=os.path.join(START_DIRECTORY, "..", "..", "htmlcov"),
|
|
95
123
|
)
|
|
96
|
-
group_coverage.add_argument("--coverage-html", metavar="DIR", help="Generate coverage HTML report")
|
|
97
124
|
group_coverage.add_argument("--coverage-xml", metavar="FILE", help="Generate coverage XML report")
|
|
98
125
|
group_coverage.add_argument(
|
|
99
126
|
"--coverage-fail-under", metavar="MIN", type=float, help="Fail if coverage percentage under min"
|
|
100
127
|
)
|
|
101
128
|
args = parser.parse_args(args=argv)
|
|
129
|
+
|
|
102
130
|
if args.coverage_branch:
|
|
103
131
|
args.coverage = args.coverage_branch
|
|
104
132
|
|
|
133
|
+
if args.coverage and not COVERAGE_AVAILABLE:
|
|
134
|
+
parser.exit(
|
|
135
|
+
status=2, message="--coverage was used, but coverage was not found. Is it installed?\n"
|
|
136
|
+
) # NVIDIA Modification
|
|
137
|
+
|
|
105
138
|
process_count = max(0, args.jobs)
|
|
106
139
|
if process_count == 0:
|
|
107
140
|
process_count = multiprocessing.cpu_count()
|
|
141
|
+
process_count = min(process_count, args.maxjobs) # NVIDIA Modification
|
|
108
142
|
|
|
109
143
|
# Create the temporary directory (for coverage files)
|
|
110
144
|
with tempfile.TemporaryDirectory() as temp_dir:
|
|
@@ -113,9 +147,10 @@ def main(argv=None):
|
|
|
113
147
|
test_loader = unittest.TestLoader()
|
|
114
148
|
if args.testNamePatterns:
|
|
115
149
|
test_loader.testNamePatterns = args.testNamePatterns
|
|
116
|
-
discover_suite =
|
|
117
|
-
|
|
118
|
-
)
|
|
150
|
+
discover_suite = warp.tests.unittest_suites.auto_discover_suite(
|
|
151
|
+
test_loader, args.pattern
|
|
152
|
+
) # NVIDIA Modification
|
|
153
|
+
# discover_suite = warp.tests.unittest_suites.explicit_suite()
|
|
119
154
|
|
|
120
155
|
# Get the parallelizable test suites
|
|
121
156
|
if args.level == "test":
|
|
@@ -128,26 +163,69 @@ def main(argv=None):
|
|
|
128
163
|
# Don't use more processes than test suites
|
|
129
164
|
process_count = max(1, min(len(test_suites), process_count))
|
|
130
165
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
166
|
+
if RUNNING_IN_TEAMCITY:
|
|
167
|
+
print(f"##teamcity[testSuiteStarted name='{TEST_SUITE_NAME}']") # NVIDIA Modification for TC
|
|
168
|
+
|
|
169
|
+
if not args.serial_fallback:
|
|
170
|
+
# Report test suites and processes
|
|
171
|
+
print(
|
|
172
|
+
f"Running {len(test_suites)} test suites ({discover_suite.countTestCases()} total tests) across {process_count} processes",
|
|
173
|
+
file=sys.stderr,
|
|
174
|
+
)
|
|
175
|
+
if args.verbose > 1:
|
|
176
|
+
print(file=sys.stderr)
|
|
177
|
+
|
|
178
|
+
# Run the tests in parallel
|
|
179
|
+
start_time = time.perf_counter()
|
|
180
|
+
|
|
181
|
+
if args.disable_concurrent_futures:
|
|
182
|
+
multiprocessing_context = multiprocessing.get_context(method="spawn")
|
|
183
|
+
maxtasksperchild = 1 if args.disable_process_pooling else None
|
|
184
|
+
with multiprocessing_context.Pool(
|
|
185
|
+
process_count,
|
|
186
|
+
maxtasksperchild=maxtasksperchild,
|
|
187
|
+
initializer=set_worker_cache,
|
|
188
|
+
initargs=(args, temp_dir),
|
|
189
|
+
) as pool, multiprocessing.Manager() as manager:
|
|
190
|
+
test_manager = ParallelTestManager(manager, args, temp_dir)
|
|
191
|
+
results = pool.map(test_manager.run_tests, test_suites)
|
|
192
|
+
else:
|
|
193
|
+
# NVIDIA Modification added concurrent.futures
|
|
194
|
+
with concurrent.futures.ProcessPoolExecutor(
|
|
195
|
+
max_workers=process_count,
|
|
196
|
+
mp_context=multiprocessing.get_context(method="spawn"),
|
|
197
|
+
initializer=set_worker_cache,
|
|
198
|
+
initargs=(args, temp_dir),
|
|
199
|
+
) as executor, multiprocessing.Manager() as manager:
|
|
200
|
+
test_manager = ParallelTestManager(manager, args, temp_dir)
|
|
201
|
+
results = list(executor.map(test_manager.run_tests, test_suites, timeout=3600))
|
|
202
|
+
else:
|
|
203
|
+
# This entire path is an NVIDIA Modification
|
|
204
|
+
|
|
205
|
+
# Report test suites and processes
|
|
206
|
+
print(f"Running {discover_suite.countTestCases()} total tests (serial fallback)", file=sys.stderr)
|
|
207
|
+
if args.verbose > 1:
|
|
208
|
+
print(file=sys.stderr)
|
|
209
|
+
|
|
210
|
+
import warp as wp
|
|
211
|
+
|
|
212
|
+
# force rebuild of all kernels
|
|
213
|
+
wp.build.clear_kernel_cache()
|
|
214
|
+
print("Cleared Warp kernel cache")
|
|
215
|
+
|
|
216
|
+
# Run the tests in serial
|
|
217
|
+
start_time = time.perf_counter()
|
|
218
|
+
|
|
219
|
+
with multiprocessing.Manager() as manager:
|
|
220
|
+
test_manager = ParallelTestManager(manager, args, temp_dir)
|
|
221
|
+
results = [test_manager.run_tests(discover_suite)]
|
|
138
222
|
|
|
139
|
-
# Run the tests in parallel
|
|
140
|
-
start_time = time.perf_counter()
|
|
141
|
-
multiprocessing_context = multiprocessing.get_context(method="spawn")
|
|
142
|
-
maxtasksperchild = 1 if args.disable_process_pooling else None
|
|
143
|
-
with multiprocessing_context.Pool(
|
|
144
|
-
process_count, maxtasksperchild=maxtasksperchild
|
|
145
|
-
) as pool, multiprocessing.Manager() as manager:
|
|
146
|
-
test_manager = ParallelTestManager(manager, args, temp_dir)
|
|
147
|
-
results = pool.map(test_manager.run_tests, test_suites)
|
|
148
223
|
stop_time = time.perf_counter()
|
|
149
224
|
test_duration = stop_time - start_time
|
|
150
225
|
|
|
226
|
+
if RUNNING_IN_TEAMCITY:
|
|
227
|
+
print(f"##teamcity[testSuiteFinished name='{TEST_SUITE_NAME}']") # NVIDIA Modification for TC
|
|
228
|
+
|
|
151
229
|
# Aggregate parallel test run results
|
|
152
230
|
tests_run = 0
|
|
153
231
|
errors = []
|
|
@@ -195,14 +273,15 @@ def main(argv=None):
|
|
|
195
273
|
|
|
196
274
|
# Return an error status on failure
|
|
197
275
|
if not is_success:
|
|
276
|
+
if RUNNING_IN_TEAMCITY:
|
|
277
|
+
print("##teamcity[buildStatus status='FAILURE']") # NVIDIA Modification for TC
|
|
198
278
|
parser.exit(status=len(errors) + len(failures) + unexpected_successes)
|
|
199
279
|
|
|
200
280
|
# Coverage?
|
|
201
281
|
if args.coverage:
|
|
202
282
|
# Combine the coverage files
|
|
203
283
|
cov_options = {}
|
|
204
|
-
|
|
205
|
-
cov_options["config_file"] = args.coverage_rcfile
|
|
284
|
+
cov_options["config_file"] = True # Grab configuration from pyproject.toml (must install coverage[toml])
|
|
206
285
|
cov = coverage.Coverage(**cov_options)
|
|
207
286
|
cov.combine(data_paths=[os.path.join(temp_dir, x) for x in os.listdir(temp_dir)])
|
|
208
287
|
|
|
@@ -225,7 +304,7 @@ def main(argv=None):
|
|
|
225
304
|
|
|
226
305
|
|
|
227
306
|
def _convert_select_pattern(pattern):
|
|
228
|
-
if
|
|
307
|
+
if "*" not in pattern:
|
|
229
308
|
return f"*{pattern}*"
|
|
230
309
|
return pattern
|
|
231
310
|
|
|
@@ -242,12 +321,9 @@ def _coverage(args, temp_dir):
|
|
|
242
321
|
cov_options = {
|
|
243
322
|
"branch": args.coverage_branch,
|
|
244
323
|
"data_file": coverage_file.name,
|
|
245
|
-
|
|
246
|
-
"omit": (args.coverage_omit if args.coverage_omit else []) + [__file__],
|
|
247
|
-
"source": args.coverage_source,
|
|
324
|
+
# NVIDIA Modification removed unneeded options
|
|
248
325
|
}
|
|
249
|
-
|
|
250
|
-
cov_options["config_file"] = args.coverage_rcfile
|
|
326
|
+
cov_options["config_file"] = True # Grab configuration from pyproject.toml (must install coverage[toml])
|
|
251
327
|
cov = coverage.Coverage(**cov_options)
|
|
252
328
|
try:
|
|
253
329
|
# Start measuring code coverage
|
|
@@ -307,7 +383,9 @@ class ParallelTestManager:
|
|
|
307
383
|
with _coverage(self.args, self.temp_dir):
|
|
308
384
|
runner = unittest.TextTestRunner(
|
|
309
385
|
stream=StringIO(),
|
|
310
|
-
resultclass=
|
|
386
|
+
resultclass=ParallelTeamCityTestResult
|
|
387
|
+
if RUNNING_IN_TEAMCITY
|
|
388
|
+
else ParallelTextTestResult, # NVIDIA Modification for TC
|
|
311
389
|
verbosity=self.args.verbose,
|
|
312
390
|
failfast=self.args.failfast,
|
|
313
391
|
buffer=self.args.buffer,
|
|
@@ -384,3 +462,128 @@ class ParallelTextTestResult(unittest.TextTestResult):
|
|
|
384
462
|
|
|
385
463
|
def printErrors(self):
|
|
386
464
|
pass
|
|
465
|
+
|
|
466
|
+
|
|
467
|
+
# NVIDIA Modifications from here until end of file
|
|
468
|
+
|
|
469
|
+
|
|
470
|
+
def set_worker_cache(args, temp_dir):
|
|
471
|
+
"""This function is run at the start of ever new process. It changes the Warp cache to avoid conflicts."""
|
|
472
|
+
|
|
473
|
+
with _coverage(args, temp_dir):
|
|
474
|
+
import warp as wp
|
|
475
|
+
from warp.thirdparty import appdirs
|
|
476
|
+
|
|
477
|
+
pid = os.getpid()
|
|
478
|
+
cache_root_dir = appdirs.user_cache_dir(
|
|
479
|
+
appname="warp", appauthor="NVIDIA Corporation", version=f"{wp.config.version}-{pid}"
|
|
480
|
+
)
|
|
481
|
+
|
|
482
|
+
wp.config.kernel_cache_dir = cache_root_dir
|
|
483
|
+
|
|
484
|
+
wp.build.clear_kernel_cache()
|
|
485
|
+
|
|
486
|
+
|
|
487
|
+
def _tc_escape(s):
|
|
488
|
+
s = s.replace("|", "||")
|
|
489
|
+
s = s.replace("\n", "|n")
|
|
490
|
+
s = s.replace("\r", "|r")
|
|
491
|
+
s = s.replace("'", "|'")
|
|
492
|
+
s = s.replace("[", "|[")
|
|
493
|
+
s = s.replace("]", "|]")
|
|
494
|
+
return s
|
|
495
|
+
|
|
496
|
+
|
|
497
|
+
class ParallelTeamCityTestResult(unittest.TextTestResult):
|
|
498
|
+
def __init__(self, stream, descriptions, verbosity):
|
|
499
|
+
stream = type(stream)(sys.stderr)
|
|
500
|
+
super().__init__(stream, descriptions, verbosity)
|
|
501
|
+
|
|
502
|
+
def startTest(self, test):
|
|
503
|
+
if self.showAll:
|
|
504
|
+
self.stream.writeln(f"{self.getDescription(test)} ...")
|
|
505
|
+
self.stream.flush()
|
|
506
|
+
self.start_time = time.perf_counter_ns()
|
|
507
|
+
super(unittest.TextTestResult, self).startTest(test)
|
|
508
|
+
|
|
509
|
+
def _add_helper(self, test, dots_message, show_all_message):
|
|
510
|
+
if self.showAll:
|
|
511
|
+
self.stream.writeln(f"{self.getDescription(test)} ... {show_all_message}")
|
|
512
|
+
elif self.dots:
|
|
513
|
+
self.stream.write(dots_message)
|
|
514
|
+
self.stream.flush()
|
|
515
|
+
|
|
516
|
+
def addSuccess(self, test):
|
|
517
|
+
super(unittest.TextTestResult, self).addSuccess(test)
|
|
518
|
+
self._add_helper(test, ".", "ok")
|
|
519
|
+
self.reportSuccess(test)
|
|
520
|
+
|
|
521
|
+
def addError(self, test, err):
|
|
522
|
+
super(unittest.TextTestResult, self).addError(test, err)
|
|
523
|
+
self._add_helper(test, "E", "ERROR")
|
|
524
|
+
self.reportFailure(test, err)
|
|
525
|
+
|
|
526
|
+
def addFailure(self, test, err):
|
|
527
|
+
super(unittest.TextTestResult, self).addFailure(test, err)
|
|
528
|
+
self._add_helper(test, "F", "FAIL")
|
|
529
|
+
self.reportFailure(test, err)
|
|
530
|
+
|
|
531
|
+
def addSkip(self, test, reason):
|
|
532
|
+
super(unittest.TextTestResult, self).addSkip(test, reason)
|
|
533
|
+
self._add_helper(test, "s", f"skipped {reason!r}")
|
|
534
|
+
self.reportIgnored(test, reason)
|
|
535
|
+
|
|
536
|
+
def addExpectedFailure(self, test, err):
|
|
537
|
+
super(unittest.TextTestResult, self).addExpectedFailure(test, err)
|
|
538
|
+
self._add_helper(test, "x", "expected failure")
|
|
539
|
+
self.reportSuccess(test)
|
|
540
|
+
|
|
541
|
+
def addUnexpectedSuccess(self, test):
|
|
542
|
+
super(unittest.TextTestResult, self).addUnexpectedSuccess(test)
|
|
543
|
+
self._add_helper(test, "u", "unexpected success")
|
|
544
|
+
self.reportFailure(test, "unexpected success")
|
|
545
|
+
|
|
546
|
+
def addSubTest(self, test, subtest, err):
|
|
547
|
+
super(unittest.TextTestResult, self).addSubTest(test, subtest, err)
|
|
548
|
+
if err is not None:
|
|
549
|
+
self._add_helper(test, "E", "ERROR")
|
|
550
|
+
self.reportSubTestFailure(test, err)
|
|
551
|
+
|
|
552
|
+
def printErrors(self):
|
|
553
|
+
pass
|
|
554
|
+
|
|
555
|
+
def reportIgnored(self, test, reason):
|
|
556
|
+
test_id = test.id()
|
|
557
|
+
reason_str = str(reason)
|
|
558
|
+
print(reason_str)
|
|
559
|
+
self.stream.writeln(f"##teamcity[testIgnored name='{test_id}' message='{_tc_escape(str(reason))}']")
|
|
560
|
+
self.stream.flush()
|
|
561
|
+
|
|
562
|
+
def reportSuccess(self, test):
|
|
563
|
+
duration = round((time.perf_counter_ns() - self.start_time) / 1e6) # [ms]
|
|
564
|
+
test_id = test.id()
|
|
565
|
+
self.stream.writeln(f"##teamcity[testStarted name='{test_id}']")
|
|
566
|
+
self.stream.writeln(f"##teamcity[testFinished name='{test_id}' duration='{duration}']")
|
|
567
|
+
self.stream.flush()
|
|
568
|
+
|
|
569
|
+
def reportFailure(self, test, err):
|
|
570
|
+
test_id = test.id()
|
|
571
|
+
self.stream.writeln(f"##teamcity[testStarted name='{test_id}']")
|
|
572
|
+
self.stream.writeln(
|
|
573
|
+
f"##teamcity[testFailed name='{test_id}' message='{_tc_escape(str(err[1]))}' details='{_tc_escape(str(err[2]))}']"
|
|
574
|
+
)
|
|
575
|
+
self.stream.writeln(f"##teamcity[testFinished name='{test_id}']")
|
|
576
|
+
self.stream.flush()
|
|
577
|
+
|
|
578
|
+
def reportSubTestFailure(self, test, err):
|
|
579
|
+
test_id = test.id()
|
|
580
|
+
self.stream.writeln(f"##teamcity[testStarted name='{test_id}']")
|
|
581
|
+
self.stream.writeln(
|
|
582
|
+
f"##teamcity[testFailed name='{test_id}' message='{_tc_escape(str(err[1]))}' details='{_tc_escape(self._exc_info_to_string(err, test))}']"
|
|
583
|
+
)
|
|
584
|
+
self.stream.writeln(f"##teamcity[testFinished name='{test_id}']")
|
|
585
|
+
self.stream.flush()
|
|
586
|
+
|
|
587
|
+
|
|
588
|
+
if __name__ == "__main__": # pragma: no cover
|
|
589
|
+
main()
|