warp-lang 1.0.2__py3-none-win_amd64.whl → 1.2.0__py3-none-win_amd64.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.
Potentially problematic release.
This version of warp-lang might be problematic. Click here for more details.
- warp/__init__.py +108 -97
- warp/__init__.pyi +1 -1
- warp/bin/warp-clang.dll +0 -0
- warp/bin/warp.dll +0 -0
- warp/build.py +88 -113
- warp/build_dll.py +383 -375
- warp/builtins.py +3693 -3354
- warp/codegen.py +2925 -2792
- warp/config.py +40 -36
- warp/constants.py +49 -45
- warp/context.py +5409 -5102
- warp/dlpack.py +442 -442
- warp/examples/__init__.py +16 -16
- warp/examples/assets/bear.usd +0 -0
- warp/examples/assets/bunny.usd +0 -0
- warp/examples/assets/cartpole.urdf +110 -110
- warp/examples/assets/crazyflie.usd +0 -0
- warp/examples/assets/cube.usd +0 -0
- warp/examples/assets/nv_ant.xml +92 -92
- warp/examples/assets/nv_humanoid.xml +183 -183
- warp/examples/assets/quadruped.urdf +267 -267
- warp/examples/assets/rocks.nvdb +0 -0
- warp/examples/assets/rocks.usd +0 -0
- warp/examples/assets/sphere.usd +0 -0
- warp/examples/benchmarks/benchmark_api.py +381 -383
- warp/examples/benchmarks/benchmark_cloth.py +278 -277
- warp/examples/benchmarks/benchmark_cloth_cupy.py +88 -88
- warp/examples/benchmarks/benchmark_cloth_jax.py +97 -100
- warp/examples/benchmarks/benchmark_cloth_numba.py +146 -142
- warp/examples/benchmarks/benchmark_cloth_numpy.py +77 -77
- warp/examples/benchmarks/benchmark_cloth_pytorch.py +86 -86
- warp/examples/benchmarks/benchmark_cloth_taichi.py +112 -112
- warp/examples/benchmarks/benchmark_cloth_warp.py +145 -146
- warp/examples/benchmarks/benchmark_launches.py +293 -295
- warp/examples/browse.py +29 -29
- warp/examples/core/example_dem.py +232 -219
- warp/examples/core/example_fluid.py +291 -267
- warp/examples/core/example_graph_capture.py +142 -126
- warp/examples/core/example_marching_cubes.py +186 -174
- warp/examples/core/example_mesh.py +172 -155
- warp/examples/core/example_mesh_intersect.py +203 -193
- warp/examples/core/example_nvdb.py +174 -170
- warp/examples/core/example_raycast.py +103 -90
- warp/examples/core/example_raymarch.py +197 -178
- warp/examples/core/example_render_opengl.py +183 -141
- warp/examples/core/example_sph.py +403 -387
- warp/examples/core/example_torch.py +219 -181
- warp/examples/core/example_wave.py +261 -248
- warp/examples/fem/bsr_utils.py +378 -380
- warp/examples/fem/example_apic_fluid.py +432 -389
- warp/examples/fem/example_burgers.py +262 -0
- warp/examples/fem/example_convection_diffusion.py +180 -168
- warp/examples/fem/example_convection_diffusion_dg.py +217 -209
- warp/examples/fem/example_deformed_geometry.py +175 -159
- warp/examples/fem/example_diffusion.py +199 -173
- warp/examples/fem/example_diffusion_3d.py +178 -152
- warp/examples/fem/example_diffusion_mgpu.py +219 -214
- warp/examples/fem/example_mixed_elasticity.py +242 -222
- warp/examples/fem/example_navier_stokes.py +257 -243
- warp/examples/fem/example_stokes.py +218 -192
- warp/examples/fem/example_stokes_transfer.py +263 -249
- warp/examples/fem/mesh_utils.py +133 -109
- warp/examples/fem/plot_utils.py +292 -287
- warp/examples/optim/example_bounce.py +258 -246
- warp/examples/optim/example_cloth_throw.py +220 -209
- warp/examples/optim/example_diffray.py +564 -536
- warp/examples/optim/example_drone.py +862 -835
- warp/examples/optim/example_inverse_kinematics.py +174 -168
- warp/examples/optim/example_inverse_kinematics_torch.py +183 -169
- warp/examples/optim/example_spring_cage.py +237 -231
- warp/examples/optim/example_trajectory.py +221 -199
- warp/examples/optim/example_walker.py +304 -293
- warp/examples/sim/example_cartpole.py +137 -129
- warp/examples/sim/example_cloth.py +194 -186
- warp/examples/sim/example_granular.py +122 -111
- warp/examples/sim/example_granular_collision_sdf.py +195 -186
- warp/examples/sim/example_jacobian_ik.py +234 -214
- warp/examples/sim/example_particle_chain.py +116 -105
- warp/examples/sim/example_quadruped.py +191 -180
- warp/examples/sim/example_rigid_chain.py +195 -187
- warp/examples/sim/example_rigid_contact.py +187 -177
- warp/examples/sim/example_rigid_force.py +125 -125
- warp/examples/sim/example_rigid_gyroscopic.py +107 -95
- warp/examples/sim/example_rigid_soft_contact.py +132 -122
- warp/examples/sim/example_soft_body.py +188 -177
- warp/fabric.py +337 -335
- warp/fem/__init__.py +61 -27
- warp/fem/cache.py +403 -388
- warp/fem/dirichlet.py +178 -179
- warp/fem/domain.py +262 -263
- warp/fem/field/__init__.py +100 -101
- warp/fem/field/field.py +148 -149
- warp/fem/field/nodal_field.py +298 -299
- warp/fem/field/restriction.py +22 -21
- warp/fem/field/test.py +180 -181
- warp/fem/field/trial.py +183 -183
- warp/fem/geometry/__init__.py +16 -19
- warp/fem/geometry/closest_point.py +69 -70
- warp/fem/geometry/deformed_geometry.py +270 -271
- warp/fem/geometry/element.py +748 -744
- warp/fem/geometry/geometry.py +184 -186
- warp/fem/geometry/grid_2d.py +380 -373
- warp/fem/geometry/grid_3d.py +437 -435
- warp/fem/geometry/hexmesh.py +953 -953
- warp/fem/geometry/nanogrid.py +455 -0
- warp/fem/geometry/partition.py +374 -376
- warp/fem/geometry/quadmesh_2d.py +532 -532
- warp/fem/geometry/tetmesh.py +840 -840
- warp/fem/geometry/trimesh_2d.py +577 -577
- warp/fem/integrate.py +1684 -1615
- warp/fem/operator.py +190 -191
- warp/fem/polynomial.py +214 -213
- warp/fem/quadrature/__init__.py +2 -2
- warp/fem/quadrature/pic_quadrature.py +243 -245
- warp/fem/quadrature/quadrature.py +295 -294
- warp/fem/space/__init__.py +179 -292
- warp/fem/space/basis_space.py +522 -489
- warp/fem/space/collocated_function_space.py +100 -105
- warp/fem/space/dof_mapper.py +236 -236
- warp/fem/space/function_space.py +148 -145
- warp/fem/space/grid_2d_function_space.py +148 -267
- warp/fem/space/grid_3d_function_space.py +167 -306
- warp/fem/space/hexmesh_function_space.py +253 -352
- warp/fem/space/nanogrid_function_space.py +202 -0
- warp/fem/space/partition.py +350 -350
- warp/fem/space/quadmesh_2d_function_space.py +261 -369
- warp/fem/space/restriction.py +161 -160
- warp/fem/space/shape/__init__.py +90 -15
- warp/fem/space/shape/cube_shape_function.py +728 -738
- warp/fem/space/shape/shape_function.py +102 -103
- warp/fem/space/shape/square_shape_function.py +611 -611
- warp/fem/space/shape/tet_shape_function.py +565 -567
- warp/fem/space/shape/triangle_shape_function.py +429 -429
- warp/fem/space/tetmesh_function_space.py +224 -292
- warp/fem/space/topology.py +297 -295
- warp/fem/space/trimesh_2d_function_space.py +153 -221
- warp/fem/types.py +77 -77
- warp/fem/utils.py +495 -495
- warp/jax.py +166 -141
- warp/jax_experimental.py +341 -339
- warp/native/array.h +1081 -1025
- warp/native/builtin.h +1603 -1560
- warp/native/bvh.cpp +402 -398
- warp/native/bvh.cu +533 -525
- warp/native/bvh.h +430 -429
- warp/native/clang/clang.cpp +496 -464
- warp/native/crt.cpp +42 -32
- warp/native/crt.h +352 -335
- warp/native/cuda_crt.h +1049 -1049
- warp/native/cuda_util.cpp +549 -540
- warp/native/cuda_util.h +288 -203
- warp/native/cutlass_gemm.cpp +34 -34
- warp/native/cutlass_gemm.cu +372 -372
- warp/native/error.cpp +66 -66
- warp/native/error.h +27 -27
- warp/native/exports.h +187 -0
- warp/native/fabric.h +228 -228
- warp/native/hashgrid.cpp +301 -278
- warp/native/hashgrid.cu +78 -77
- warp/native/hashgrid.h +227 -227
- warp/native/initializer_array.h +32 -32
- warp/native/intersect.h +1204 -1204
- warp/native/intersect_adj.h +365 -365
- warp/native/intersect_tri.h +322 -322
- warp/native/marching.cpp +2 -2
- warp/native/marching.cu +497 -497
- warp/native/marching.h +2 -2
- warp/native/mat.h +1545 -1498
- warp/native/matnn.h +333 -333
- warp/native/mesh.cpp +203 -203
- warp/native/mesh.cu +292 -293
- warp/native/mesh.h +1887 -1887
- warp/native/nanovdb/GridHandle.h +366 -0
- warp/native/nanovdb/HostBuffer.h +590 -0
- warp/native/nanovdb/NanoVDB.h +6624 -4782
- warp/native/nanovdb/PNanoVDB.h +3390 -2553
- warp/native/noise.h +850 -850
- warp/native/quat.h +1112 -1085
- warp/native/rand.h +303 -299
- warp/native/range.h +108 -108
- warp/native/reduce.cpp +156 -156
- warp/native/reduce.cu +348 -348
- warp/native/runlength_encode.cpp +61 -61
- warp/native/runlength_encode.cu +46 -46
- warp/native/scan.cpp +30 -30
- warp/native/scan.cu +36 -36
- warp/native/scan.h +7 -7
- warp/native/solid_angle.h +442 -442
- warp/native/sort.cpp +94 -94
- warp/native/sort.cu +97 -97
- warp/native/sort.h +14 -14
- warp/native/sparse.cpp +337 -337
- warp/native/sparse.cu +544 -544
- warp/native/spatial.h +630 -630
- warp/native/svd.h +562 -562
- warp/native/temp_buffer.h +30 -30
- warp/native/vec.h +1177 -1133
- warp/native/volume.cpp +529 -297
- warp/native/volume.cu +58 -32
- warp/native/volume.h +960 -538
- warp/native/volume_builder.cu +446 -425
- warp/native/volume_builder.h +34 -19
- warp/native/volume_impl.h +61 -0
- warp/native/warp.cpp +1057 -1052
- warp/native/warp.cu +2949 -2828
- warp/native/warp.h +321 -305
- warp/optim/__init__.py +9 -9
- warp/optim/adam.py +120 -120
- warp/optim/linear.py +1104 -939
- warp/optim/sgd.py +104 -92
- warp/render/__init__.py +10 -10
- warp/render/render_opengl.py +3356 -3204
- warp/render/render_usd.py +768 -749
- warp/render/utils.py +152 -150
- warp/sim/__init__.py +52 -59
- warp/sim/articulation.py +685 -685
- warp/sim/collide.py +1594 -1590
- warp/sim/import_mjcf.py +489 -481
- warp/sim/import_snu.py +220 -221
- warp/sim/import_urdf.py +536 -516
- warp/sim/import_usd.py +887 -881
- warp/sim/inertia.py +316 -317
- warp/sim/integrator.py +234 -233
- warp/sim/integrator_euler.py +1956 -1956
- warp/sim/integrator_featherstone.py +1917 -1991
- warp/sim/integrator_xpbd.py +3288 -3312
- warp/sim/model.py +4473 -4314
- warp/sim/particles.py +113 -112
- warp/sim/render.py +417 -403
- warp/sim/utils.py +413 -410
- warp/sparse.py +1289 -1227
- warp/stubs.py +2192 -2469
- warp/tape.py +1162 -225
- warp/tests/__init__.py +1 -1
- warp/tests/__main__.py +4 -4
- warp/tests/assets/test_index_grid.nvdb +0 -0
- warp/tests/assets/torus.usda +105 -105
- warp/tests/aux_test_class_kernel.py +26 -26
- warp/tests/aux_test_compile_consts_dummy.py +10 -10
- warp/tests/aux_test_conditional_unequal_types_kernels.py +21 -21
- warp/tests/aux_test_dependent.py +20 -22
- warp/tests/aux_test_grad_customs.py +21 -23
- warp/tests/aux_test_reference.py +9 -11
- warp/tests/aux_test_reference_reference.py +8 -10
- warp/tests/aux_test_square.py +15 -17
- warp/tests/aux_test_unresolved_func.py +14 -14
- warp/tests/aux_test_unresolved_symbol.py +14 -14
- warp/tests/disabled_kinematics.py +237 -239
- warp/tests/run_coverage_serial.py +31 -31
- warp/tests/test_adam.py +155 -157
- warp/tests/test_arithmetic.py +1088 -1124
- warp/tests/test_array.py +2415 -2326
- warp/tests/test_array_reduce.py +148 -150
- warp/tests/test_async.py +666 -656
- warp/tests/test_atomic.py +139 -141
- warp/tests/test_bool.py +212 -149
- warp/tests/test_builtins_resolution.py +1290 -1292
- warp/tests/test_bvh.py +162 -171
- warp/tests/test_closest_point_edge_edge.py +227 -228
- warp/tests/test_codegen.py +562 -553
- warp/tests/test_compile_consts.py +217 -101
- warp/tests/test_conditional.py +244 -246
- warp/tests/test_copy.py +230 -215
- warp/tests/test_ctypes.py +630 -632
- warp/tests/test_dense.py +65 -67
- warp/tests/test_devices.py +89 -98
- warp/tests/test_dlpack.py +528 -529
- warp/tests/test_examples.py +403 -378
- warp/tests/test_fabricarray.py +952 -955
- warp/tests/test_fast_math.py +60 -54
- warp/tests/test_fem.py +1298 -1278
- warp/tests/test_fp16.py +128 -130
- warp/tests/test_func.py +336 -337
- warp/tests/test_generics.py +596 -571
- warp/tests/test_grad.py +885 -640
- warp/tests/test_grad_customs.py +331 -336
- warp/tests/test_hash_grid.py +208 -164
- warp/tests/test_import.py +37 -39
- warp/tests/test_indexedarray.py +1132 -1134
- warp/tests/test_intersect.py +65 -67
- warp/tests/test_jax.py +305 -307
- warp/tests/test_large.py +169 -164
- warp/tests/test_launch.py +352 -354
- warp/tests/test_lerp.py +217 -261
- warp/tests/test_linear_solvers.py +189 -171
- warp/tests/test_lvalue.py +419 -493
- warp/tests/test_marching_cubes.py +63 -65
- warp/tests/test_mat.py +1799 -1827
- warp/tests/test_mat_lite.py +113 -115
- warp/tests/test_mat_scalar_ops.py +2905 -2889
- warp/tests/test_math.py +124 -193
- warp/tests/test_matmul.py +498 -499
- warp/tests/test_matmul_lite.py +408 -410
- warp/tests/test_mempool.py +186 -190
- warp/tests/test_mesh.py +281 -324
- warp/tests/test_mesh_query_aabb.py +226 -241
- warp/tests/test_mesh_query_point.py +690 -702
- warp/tests/test_mesh_query_ray.py +290 -303
- warp/tests/test_mlp.py +274 -276
- warp/tests/test_model.py +108 -110
- warp/tests/test_module_hashing.py +111 -0
- warp/tests/test_modules_lite.py +36 -39
- warp/tests/test_multigpu.py +161 -163
- warp/tests/test_noise.py +244 -248
- warp/tests/test_operators.py +248 -250
- warp/tests/test_options.py +121 -125
- warp/tests/test_peer.py +131 -137
- warp/tests/test_pinned.py +76 -78
- warp/tests/test_print.py +52 -54
- warp/tests/test_quat.py +2084 -2086
- warp/tests/test_rand.py +324 -288
- warp/tests/test_reload.py +207 -217
- warp/tests/test_rounding.py +177 -179
- warp/tests/test_runlength_encode.py +188 -190
- warp/tests/test_sim_grad.py +241 -0
- warp/tests/test_sim_kinematics.py +89 -97
- warp/tests/test_smoothstep.py +166 -168
- warp/tests/test_snippet.py +303 -266
- warp/tests/test_sparse.py +466 -460
- warp/tests/test_spatial.py +2146 -2148
- warp/tests/test_special_values.py +362 -0
- warp/tests/test_streams.py +484 -473
- warp/tests/test_struct.py +708 -675
- warp/tests/test_tape.py +171 -148
- warp/tests/test_torch.py +741 -743
- warp/tests/test_transient_module.py +85 -87
- warp/tests/test_types.py +554 -659
- warp/tests/test_utils.py +488 -499
- warp/tests/test_vec.py +1262 -1268
- warp/tests/test_vec_lite.py +71 -73
- warp/tests/test_vec_scalar_ops.py +2097 -2099
- warp/tests/test_verify_fp.py +92 -94
- warp/tests/test_volume.py +961 -736
- warp/tests/test_volume_write.py +338 -265
- warp/tests/unittest_serial.py +38 -37
- warp/tests/unittest_suites.py +367 -359
- warp/tests/unittest_utils.py +434 -578
- warp/tests/unused_test_misc.py +69 -71
- warp/tests/walkthrough_debug.py +85 -85
- warp/thirdparty/appdirs.py +598 -598
- warp/thirdparty/dlpack.py +143 -143
- warp/thirdparty/unittest_parallel.py +563 -561
- warp/torch.py +321 -295
- warp/types.py +4941 -4450
- warp/utils.py +1008 -821
- {warp_lang-1.0.2.dist-info → warp_lang-1.2.0.dist-info}/LICENSE.md +126 -126
- {warp_lang-1.0.2.dist-info → warp_lang-1.2.0.dist-info}/METADATA +365 -400
- warp_lang-1.2.0.dist-info/RECORD +359 -0
- warp/examples/assets/cube.usda +0 -42
- warp/examples/assets/sphere.usda +0 -56
- warp/examples/assets/torus.usda +0 -105
- warp/examples/fem/example_convection_diffusion_dg0.py +0 -194
- warp/native/nanovdb/PNanoVDBWrite.h +0 -295
- warp_lang-1.0.2.dist-info/RECORD +0 -352
- {warp_lang-1.0.2.dist-info → warp_lang-1.2.0.dist-info}/WHEEL +0 -0
- {warp_lang-1.0.2.dist-info → warp_lang-1.2.0.dist-info}/top_level.txt +0 -0
|
@@ -1,561 +1,563 @@
|
|
|
1
|
-
# Licensed under the MIT License
|
|
2
|
-
# https://github.com/craigahobbs/unittest-parallel/blob/main/LICENSE
|
|
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
|
-
|
|
14
|
-
"""
|
|
15
|
-
unittest-parallel command-line script main module
|
|
16
|
-
"""
|
|
17
|
-
|
|
18
|
-
import argparse
|
|
19
|
-
import concurrent.futures # NVIDIA Modification
|
|
20
|
-
import multiprocessing
|
|
21
|
-
import os
|
|
22
|
-
import sys
|
|
23
|
-
import tempfile
|
|
24
|
-
import time
|
|
25
|
-
import unittest
|
|
26
|
-
from contextlib import contextmanager
|
|
27
|
-
from io import StringIO
|
|
28
|
-
|
|
29
|
-
import warp.tests.unittest_suites # NVIDIA Modification
|
|
30
|
-
from warp.tests.unittest_utils import ( # NVIDIA modification
|
|
31
|
-
ParallelJunitTestResult,
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
# The
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
)
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
parser.add_argument(
|
|
70
|
-
"-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
"
|
|
81
|
-
"
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
"
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
help="
|
|
91
|
-
)
|
|
92
|
-
parser.add_argument(
|
|
93
|
-
"
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
"
|
|
97
|
-
"
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
"
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
"
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
"
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
"
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
group_coverage
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
"
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
# Run the tests in serial
|
|
257
|
-
start_time = time.perf_counter()
|
|
258
|
-
|
|
259
|
-
with multiprocessing.Manager() as manager:
|
|
260
|
-
test_manager = ParallelTestManager(manager, args, temp_dir)
|
|
261
|
-
results = [test_manager.run_tests(discover_suite)]
|
|
262
|
-
|
|
263
|
-
stop_time = time.perf_counter()
|
|
264
|
-
test_duration = stop_time - start_time
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
print(
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
#
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
cov_options =
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
#
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
def
|
|
427
|
-
|
|
428
|
-
self.
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
if
|
|
439
|
-
resultclass =
|
|
440
|
-
|
|
441
|
-
resultclass =
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
result.
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
self.stream.
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
self.
|
|
507
|
-
|
|
508
|
-
def
|
|
509
|
-
super(unittest.TextTestResult, self).
|
|
510
|
-
self._add_helper(test, "
|
|
511
|
-
|
|
512
|
-
def
|
|
513
|
-
super(unittest.TextTestResult, self).
|
|
514
|
-
self._add_helper(test, "
|
|
515
|
-
|
|
516
|
-
def
|
|
517
|
-
super(unittest.TextTestResult, self).
|
|
518
|
-
self._add_helper(test, "
|
|
519
|
-
|
|
520
|
-
def
|
|
521
|
-
super(unittest.TextTestResult, self).
|
|
522
|
-
self._add_helper(test, "
|
|
523
|
-
|
|
524
|
-
def
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
1
|
+
# Licensed under the MIT License
|
|
2
|
+
# https://github.com/craigahobbs/unittest-parallel/blob/main/LICENSE
|
|
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
|
+
|
|
14
|
+
"""
|
|
15
|
+
unittest-parallel command-line script main module
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
import argparse
|
|
19
|
+
import concurrent.futures # NVIDIA Modification
|
|
20
|
+
import multiprocessing
|
|
21
|
+
import os
|
|
22
|
+
import sys
|
|
23
|
+
import tempfile
|
|
24
|
+
import time
|
|
25
|
+
import unittest
|
|
26
|
+
from contextlib import contextmanager
|
|
27
|
+
from io import StringIO
|
|
28
|
+
|
|
29
|
+
import warp.tests.unittest_suites # NVIDIA Modification
|
|
30
|
+
from warp.tests.unittest_utils import ( # NVIDIA modification
|
|
31
|
+
ParallelJunitTestResult,
|
|
32
|
+
write_junit_results,
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
try:
|
|
36
|
+
import coverage
|
|
37
|
+
|
|
38
|
+
COVERAGE_AVAILABLE = True # NVIDIA Modification
|
|
39
|
+
except ImportError:
|
|
40
|
+
COVERAGE_AVAILABLE = False # NVIDIA Modification
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
# The following variables are NVIDIA Modifications
|
|
44
|
+
START_DIRECTORY = os.path.dirname(__file__) # The directory to start test discovery
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def main(argv=None):
|
|
48
|
+
"""
|
|
49
|
+
unittest-parallel command-line script main entry point
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
# Command line arguments
|
|
53
|
+
parser = argparse.ArgumentParser(
|
|
54
|
+
prog="unittest-parallel",
|
|
55
|
+
# NVIDIA Modifications follow:
|
|
56
|
+
formatter_class=argparse.RawTextHelpFormatter,
|
|
57
|
+
epilog="""Example usage:
|
|
58
|
+
python -m warp.tests -s autodetect -p 'test_a*.py'
|
|
59
|
+
python -m warp.tests -s kit
|
|
60
|
+
python -m warp.tests -k 'mgpu' -k 'cuda'
|
|
61
|
+
""",
|
|
62
|
+
)
|
|
63
|
+
# parser.add_argument("-v", "--verbose", action="store_const", const=2, default=1, help="Verbose output")
|
|
64
|
+
parser.add_argument("-q", "--quiet", dest="verbose", action="store_const", const=0, default=2, help="Quiet output")
|
|
65
|
+
parser.add_argument("-f", "--failfast", action="store_true", default=False, help="Stop on first fail or error")
|
|
66
|
+
parser.add_argument(
|
|
67
|
+
"-b", "--buffer", action="store_true", default=False, help="Buffer stdout and stderr during tests"
|
|
68
|
+
)
|
|
69
|
+
parser.add_argument(
|
|
70
|
+
"-k",
|
|
71
|
+
dest="testNamePatterns",
|
|
72
|
+
action="append",
|
|
73
|
+
type=_convert_select_pattern,
|
|
74
|
+
help="Only run tests which match the given substring",
|
|
75
|
+
)
|
|
76
|
+
parser.add_argument(
|
|
77
|
+
"-p",
|
|
78
|
+
"--pattern",
|
|
79
|
+
metavar="PATTERN",
|
|
80
|
+
default="test*.py",
|
|
81
|
+
help="'autodetect' suite only: Pattern to match tests ('test*.py' default)", # NVIDIA Modification
|
|
82
|
+
)
|
|
83
|
+
parser.add_argument(
|
|
84
|
+
"-t",
|
|
85
|
+
"--top-level-directory",
|
|
86
|
+
metavar="TOP",
|
|
87
|
+
help="Top level directory of project (defaults to start directory)",
|
|
88
|
+
)
|
|
89
|
+
parser.add_argument(
|
|
90
|
+
"--junit-report-xml", metavar="FILE", help="Generate JUnit report format XML file"
|
|
91
|
+
) # NVIDIA Modification
|
|
92
|
+
parser.add_argument(
|
|
93
|
+
"-s",
|
|
94
|
+
"--suite",
|
|
95
|
+
type=str,
|
|
96
|
+
default="default",
|
|
97
|
+
choices=["autodetect", "default", "kit"],
|
|
98
|
+
help="Name of the test suite to run (default is 'default').",
|
|
99
|
+
) # NVIDIA Modification
|
|
100
|
+
group_parallel = parser.add_argument_group("parallelization options")
|
|
101
|
+
group_parallel.add_argument(
|
|
102
|
+
"-j",
|
|
103
|
+
"--jobs",
|
|
104
|
+
metavar="COUNT",
|
|
105
|
+
type=int,
|
|
106
|
+
default=0,
|
|
107
|
+
help="The number of test processes (default is 0, all cores)",
|
|
108
|
+
)
|
|
109
|
+
group_parallel.add_argument(
|
|
110
|
+
"-m",
|
|
111
|
+
"--maxjobs",
|
|
112
|
+
metavar="MAXCOUNT",
|
|
113
|
+
type=int,
|
|
114
|
+
default=8,
|
|
115
|
+
help="The maximum number of test processes (default is 8)",
|
|
116
|
+
) # NVIDIA Modification
|
|
117
|
+
group_parallel.add_argument(
|
|
118
|
+
"--level",
|
|
119
|
+
choices=["module", "class", "test"],
|
|
120
|
+
default="class",
|
|
121
|
+
help="Set the test parallelism level (default is 'class')",
|
|
122
|
+
)
|
|
123
|
+
group_parallel.add_argument(
|
|
124
|
+
"--disable-process-pooling",
|
|
125
|
+
action="store_true",
|
|
126
|
+
default=False,
|
|
127
|
+
help="Do not reuse processes used to run test suites",
|
|
128
|
+
)
|
|
129
|
+
group_parallel.add_argument(
|
|
130
|
+
"--disable-concurrent-futures",
|
|
131
|
+
action="store_true",
|
|
132
|
+
default=False,
|
|
133
|
+
help="Use multiprocessing instead of concurrent.futures.",
|
|
134
|
+
) # NVIDIA Modification
|
|
135
|
+
group_parallel.add_argument(
|
|
136
|
+
"--serial-fallback",
|
|
137
|
+
action="store_true",
|
|
138
|
+
default=False,
|
|
139
|
+
help="Run in a single-process (no spawning) mode without multiprocessing or concurrent.futures.",
|
|
140
|
+
) # NVIDIA Modification
|
|
141
|
+
group_coverage = parser.add_argument_group("coverage options")
|
|
142
|
+
group_coverage.add_argument("--coverage", action="store_true", help="Run tests with coverage")
|
|
143
|
+
group_coverage.add_argument("--coverage-branch", action="store_true", help="Run tests with branch coverage")
|
|
144
|
+
group_coverage.add_argument(
|
|
145
|
+
"--coverage-html",
|
|
146
|
+
metavar="DIR",
|
|
147
|
+
help="Generate coverage HTML report",
|
|
148
|
+
default=os.path.join(START_DIRECTORY, "..", "..", "htmlcov"),
|
|
149
|
+
)
|
|
150
|
+
group_coverage.add_argument("--coverage-xml", metavar="FILE", help="Generate coverage XML report")
|
|
151
|
+
group_coverage.add_argument(
|
|
152
|
+
"--coverage-fail-under", metavar="MIN", type=float, help="Fail if coverage percentage under min"
|
|
153
|
+
)
|
|
154
|
+
group_warp = parser.add_argument_group("NVIDIA Warp options") # NVIDIA Modification
|
|
155
|
+
group_warp.add_argument(
|
|
156
|
+
"--no-shared-cache", action="store_true", help="Use a separate kernel cache per test process."
|
|
157
|
+
)
|
|
158
|
+
args = parser.parse_args(args=argv)
|
|
159
|
+
|
|
160
|
+
if args.coverage_branch:
|
|
161
|
+
args.coverage = args.coverage_branch
|
|
162
|
+
|
|
163
|
+
if args.coverage and not COVERAGE_AVAILABLE:
|
|
164
|
+
parser.exit(
|
|
165
|
+
status=2, message="--coverage was used, but coverage was not found. Is it installed?\n"
|
|
166
|
+
) # NVIDIA Modification
|
|
167
|
+
|
|
168
|
+
process_count = max(0, args.jobs)
|
|
169
|
+
if process_count == 0:
|
|
170
|
+
process_count = multiprocessing.cpu_count()
|
|
171
|
+
process_count = min(process_count, args.maxjobs) # NVIDIA Modification
|
|
172
|
+
|
|
173
|
+
import warp as wp # NVIDIA Modification
|
|
174
|
+
|
|
175
|
+
# Clear the Warp cache (NVIDIA Modification)
|
|
176
|
+
wp.build.clear_kernel_cache()
|
|
177
|
+
print("Cleared Warp kernel cache")
|
|
178
|
+
|
|
179
|
+
# Create the temporary directory (for coverage files)
|
|
180
|
+
with tempfile.TemporaryDirectory() as temp_dir:
|
|
181
|
+
# Discover tests
|
|
182
|
+
with _coverage(args, temp_dir):
|
|
183
|
+
test_loader = unittest.TestLoader()
|
|
184
|
+
if args.testNamePatterns:
|
|
185
|
+
test_loader.testNamePatterns = args.testNamePatterns
|
|
186
|
+
|
|
187
|
+
auto_discover_suite = warp.tests.unittest_suites.auto_discover_suite(
|
|
188
|
+
test_loader, args.pattern
|
|
189
|
+
) # NVIDIA Modification
|
|
190
|
+
|
|
191
|
+
# NVIDIA Modification
|
|
192
|
+
if args.suite != "autodetect":
|
|
193
|
+
# Print notices for test classes missing from the suite when compared to auto-discovered tests
|
|
194
|
+
discover_suite = warp.tests.unittest_suites.compare_unittest_suites(
|
|
195
|
+
test_loader, args.suite, auto_discover_suite
|
|
196
|
+
)
|
|
197
|
+
else:
|
|
198
|
+
discover_suite = auto_discover_suite
|
|
199
|
+
|
|
200
|
+
# Get the parallelizable test suites
|
|
201
|
+
if args.level == "test":
|
|
202
|
+
test_suites = list(_iter_test_cases(discover_suite))
|
|
203
|
+
elif args.level == "class":
|
|
204
|
+
test_suites = list(_iter_class_suites(discover_suite))
|
|
205
|
+
else: # args.level == 'module'
|
|
206
|
+
test_suites = list(_iter_module_suites(discover_suite))
|
|
207
|
+
|
|
208
|
+
# Don't use more processes than test suites
|
|
209
|
+
process_count = max(1, min(len(test_suites), process_count))
|
|
210
|
+
|
|
211
|
+
if not args.serial_fallback:
|
|
212
|
+
# Report test suites and processes
|
|
213
|
+
print(
|
|
214
|
+
f"Running {len(test_suites)} test suites ({discover_suite.countTestCases()} total tests) across {process_count} processes",
|
|
215
|
+
file=sys.stderr,
|
|
216
|
+
)
|
|
217
|
+
if args.verbose > 1:
|
|
218
|
+
print(file=sys.stderr)
|
|
219
|
+
|
|
220
|
+
# Create the shared index object used in Warp caches (NVIDIA Modification)
|
|
221
|
+
manager = multiprocessing.Manager()
|
|
222
|
+
shared_index = manager.Value("i", -1)
|
|
223
|
+
|
|
224
|
+
# Run the tests in parallel
|
|
225
|
+
start_time = time.perf_counter()
|
|
226
|
+
|
|
227
|
+
if args.disable_concurrent_futures:
|
|
228
|
+
multiprocessing_context = multiprocessing.get_context(method="spawn")
|
|
229
|
+
maxtasksperchild = 1 if args.disable_process_pooling else None
|
|
230
|
+
with multiprocessing_context.Pool(
|
|
231
|
+
process_count,
|
|
232
|
+
maxtasksperchild=maxtasksperchild,
|
|
233
|
+
initializer=initialize_test_process,
|
|
234
|
+
initargs=(manager.Lock(), shared_index, args, temp_dir),
|
|
235
|
+
) as pool:
|
|
236
|
+
test_manager = ParallelTestManager(manager, args, temp_dir)
|
|
237
|
+
results = pool.map(test_manager.run_tests, test_suites)
|
|
238
|
+
else:
|
|
239
|
+
# NVIDIA Modification added concurrent.futures
|
|
240
|
+
with concurrent.futures.ProcessPoolExecutor(
|
|
241
|
+
max_workers=process_count,
|
|
242
|
+
mp_context=multiprocessing.get_context(method="spawn"),
|
|
243
|
+
initializer=initialize_test_process,
|
|
244
|
+
initargs=(manager.Lock(), shared_index, args, temp_dir),
|
|
245
|
+
) as executor:
|
|
246
|
+
test_manager = ParallelTestManager(manager, args, temp_dir)
|
|
247
|
+
results = list(executor.map(test_manager.run_tests, test_suites, timeout=7200))
|
|
248
|
+
else:
|
|
249
|
+
# This entire path is an NVIDIA Modification
|
|
250
|
+
|
|
251
|
+
# Report test suites and processes
|
|
252
|
+
print(f"Running {discover_suite.countTestCases()} total tests (serial fallback)", file=sys.stderr)
|
|
253
|
+
if args.verbose > 1:
|
|
254
|
+
print(file=sys.stderr)
|
|
255
|
+
|
|
256
|
+
# Run the tests in serial
|
|
257
|
+
start_time = time.perf_counter()
|
|
258
|
+
|
|
259
|
+
with multiprocessing.Manager() as manager:
|
|
260
|
+
test_manager = ParallelTestManager(manager, args, temp_dir)
|
|
261
|
+
results = [test_manager.run_tests(discover_suite)]
|
|
262
|
+
|
|
263
|
+
stop_time = time.perf_counter()
|
|
264
|
+
test_duration = stop_time - start_time
|
|
265
|
+
|
|
266
|
+
# Aggregate parallel test run results
|
|
267
|
+
tests_run = 0
|
|
268
|
+
errors = []
|
|
269
|
+
failures = []
|
|
270
|
+
skipped = 0
|
|
271
|
+
expected_failures = 0
|
|
272
|
+
unexpected_successes = 0
|
|
273
|
+
test_records = [] # NVIDIA Modification
|
|
274
|
+
for result in results:
|
|
275
|
+
tests_run += result[0]
|
|
276
|
+
errors.extend(result[1])
|
|
277
|
+
failures.extend(result[2])
|
|
278
|
+
skipped += result[3]
|
|
279
|
+
expected_failures += result[4]
|
|
280
|
+
unexpected_successes += result[5]
|
|
281
|
+
test_records += result[6] # NVIDIA Modification
|
|
282
|
+
is_success = not (errors or failures or unexpected_successes)
|
|
283
|
+
|
|
284
|
+
# Compute test info
|
|
285
|
+
infos = []
|
|
286
|
+
if failures:
|
|
287
|
+
infos.append(f"failures={len(failures)}")
|
|
288
|
+
if errors:
|
|
289
|
+
infos.append(f"errors={len(errors)}")
|
|
290
|
+
if skipped:
|
|
291
|
+
infos.append(f"skipped={skipped}")
|
|
292
|
+
if expected_failures:
|
|
293
|
+
infos.append(f"expected failures={expected_failures}")
|
|
294
|
+
if unexpected_successes:
|
|
295
|
+
infos.append(f"unexpected successes={unexpected_successes}")
|
|
296
|
+
|
|
297
|
+
# Report test errors
|
|
298
|
+
if errors or failures:
|
|
299
|
+
print(file=sys.stderr)
|
|
300
|
+
for error in errors:
|
|
301
|
+
print(error, file=sys.stderr)
|
|
302
|
+
for failure in failures:
|
|
303
|
+
print(failure, file=sys.stderr)
|
|
304
|
+
elif args.verbose > 0:
|
|
305
|
+
print(file=sys.stderr)
|
|
306
|
+
|
|
307
|
+
# Test report
|
|
308
|
+
print(unittest.TextTestResult.separator2, file=sys.stderr)
|
|
309
|
+
print(f'Ran {tests_run} {"tests" if tests_run > 1 else "test"} in {test_duration:.3f}s', file=sys.stderr)
|
|
310
|
+
print(file=sys.stderr)
|
|
311
|
+
print(f'{"OK" if is_success else "FAILED"}{" (" + ", ".join(infos) + ")" if infos else ""}', file=sys.stderr)
|
|
312
|
+
|
|
313
|
+
if test_records and args.junit_report_xml:
|
|
314
|
+
# NVIDIA modification to report results in Junit XML format
|
|
315
|
+
write_junit_results(
|
|
316
|
+
args.junit_report_xml,
|
|
317
|
+
test_records,
|
|
318
|
+
tests_run,
|
|
319
|
+
len(failures) + unexpected_successes,
|
|
320
|
+
len(errors),
|
|
321
|
+
skipped,
|
|
322
|
+
test_duration,
|
|
323
|
+
)
|
|
324
|
+
|
|
325
|
+
# Return an error status on failure
|
|
326
|
+
if not is_success:
|
|
327
|
+
parser.exit(status=len(errors) + len(failures) + unexpected_successes)
|
|
328
|
+
|
|
329
|
+
# Coverage?
|
|
330
|
+
if args.coverage:
|
|
331
|
+
# Combine the coverage files
|
|
332
|
+
cov_options = {}
|
|
333
|
+
cov_options["config_file"] = True # Grab configuration from pyproject.toml (must install coverage[toml])
|
|
334
|
+
cov = coverage.Coverage(**cov_options)
|
|
335
|
+
cov.combine(data_paths=[os.path.join(temp_dir, x) for x in os.listdir(temp_dir)])
|
|
336
|
+
|
|
337
|
+
# Coverage report
|
|
338
|
+
print(file=sys.stderr)
|
|
339
|
+
percent_covered = cov.report(ignore_errors=True, file=sys.stderr)
|
|
340
|
+
print(f"Total coverage is {percent_covered:.2f}%", file=sys.stderr)
|
|
341
|
+
|
|
342
|
+
# HTML coverage report
|
|
343
|
+
if args.coverage_html:
|
|
344
|
+
cov.html_report(directory=args.coverage_html, ignore_errors=True)
|
|
345
|
+
|
|
346
|
+
# XML coverage report
|
|
347
|
+
if args.coverage_xml:
|
|
348
|
+
cov.xml_report(outfile=args.coverage_xml, ignore_errors=True)
|
|
349
|
+
|
|
350
|
+
# Fail under
|
|
351
|
+
if args.coverage_fail_under and percent_covered < args.coverage_fail_under:
|
|
352
|
+
parser.exit(status=2)
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
def _convert_select_pattern(pattern):
|
|
356
|
+
if "*" not in pattern:
|
|
357
|
+
return f"*{pattern}*"
|
|
358
|
+
return pattern
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
@contextmanager
|
|
362
|
+
def _coverage(args, temp_dir):
|
|
363
|
+
# Running tests with coverage?
|
|
364
|
+
if args.coverage:
|
|
365
|
+
# Generate a random coverage data file name - file is deleted along with containing directory
|
|
366
|
+
with tempfile.NamedTemporaryFile(dir=temp_dir, delete=False) as coverage_file:
|
|
367
|
+
pass
|
|
368
|
+
|
|
369
|
+
# Create the coverage object
|
|
370
|
+
cov_options = {
|
|
371
|
+
"branch": args.coverage_branch,
|
|
372
|
+
"data_file": coverage_file.name,
|
|
373
|
+
# NVIDIA Modification removed unneeded options
|
|
374
|
+
}
|
|
375
|
+
cov_options["config_file"] = True # Grab configuration from pyproject.toml (must install coverage[toml])
|
|
376
|
+
cov = coverage.Coverage(**cov_options)
|
|
377
|
+
try:
|
|
378
|
+
# Start measuring code coverage
|
|
379
|
+
cov.start()
|
|
380
|
+
|
|
381
|
+
# Yield for unit test running
|
|
382
|
+
yield cov
|
|
383
|
+
finally:
|
|
384
|
+
# Stop measuring code coverage
|
|
385
|
+
cov.stop()
|
|
386
|
+
|
|
387
|
+
# Save the collected coverage data to the data file
|
|
388
|
+
cov.save()
|
|
389
|
+
else:
|
|
390
|
+
# Not running tests with coverage - yield for unit test running
|
|
391
|
+
yield None
|
|
392
|
+
|
|
393
|
+
|
|
394
|
+
# Iterate module-level test suites - all top-level test suites returned from TestLoader.discover
|
|
395
|
+
def _iter_module_suites(test_suite):
|
|
396
|
+
for module_suite in test_suite:
|
|
397
|
+
if module_suite.countTestCases():
|
|
398
|
+
yield module_suite
|
|
399
|
+
|
|
400
|
+
|
|
401
|
+
# Iterate class-level test suites - test suites that contains test cases
|
|
402
|
+
def _iter_class_suites(test_suite):
|
|
403
|
+
has_cases = any(isinstance(suite, unittest.TestCase) for suite in test_suite)
|
|
404
|
+
if has_cases:
|
|
405
|
+
yield test_suite
|
|
406
|
+
else:
|
|
407
|
+
for suite in test_suite:
|
|
408
|
+
yield from _iter_class_suites(suite)
|
|
409
|
+
|
|
410
|
+
|
|
411
|
+
# Iterate test cases (methods)
|
|
412
|
+
def _iter_test_cases(test_suite):
|
|
413
|
+
if isinstance(test_suite, unittest.TestCase):
|
|
414
|
+
yield test_suite
|
|
415
|
+
else:
|
|
416
|
+
for suite in test_suite:
|
|
417
|
+
yield from _iter_test_cases(suite)
|
|
418
|
+
|
|
419
|
+
|
|
420
|
+
class ParallelTestManager:
|
|
421
|
+
def __init__(self, manager, args, temp_dir):
|
|
422
|
+
self.args = args
|
|
423
|
+
self.temp_dir = temp_dir
|
|
424
|
+
self.failfast = manager.Event()
|
|
425
|
+
|
|
426
|
+
def run_tests(self, test_suite):
|
|
427
|
+
# Fail fast?
|
|
428
|
+
if self.failfast.is_set():
|
|
429
|
+
return [0, [], [], 0, 0, 0, []] # NVIDIA Modification
|
|
430
|
+
|
|
431
|
+
# NVIDIA Modification for GitLab
|
|
432
|
+
import warp.tests.unittest_utils
|
|
433
|
+
|
|
434
|
+
warp.tests.unittest_utils.coverage_enabled = self.args.coverage
|
|
435
|
+
warp.tests.unittest_utils.coverage_temp_dir = self.temp_dir
|
|
436
|
+
warp.tests.unittest_utils.coverage_branch = self.args.coverage_branch
|
|
437
|
+
|
|
438
|
+
if self.args.junit_report_xml:
|
|
439
|
+
resultclass = ParallelJunitTestResult
|
|
440
|
+
else:
|
|
441
|
+
resultclass = ParallelTextTestResult
|
|
442
|
+
|
|
443
|
+
# Run unit tests
|
|
444
|
+
with _coverage(self.args, self.temp_dir):
|
|
445
|
+
runner = unittest.TextTestRunner(
|
|
446
|
+
stream=StringIO(),
|
|
447
|
+
resultclass=resultclass, # NVIDIA Modification
|
|
448
|
+
verbosity=self.args.verbose,
|
|
449
|
+
failfast=self.args.failfast,
|
|
450
|
+
buffer=self.args.buffer,
|
|
451
|
+
)
|
|
452
|
+
result = runner.run(test_suite)
|
|
453
|
+
|
|
454
|
+
# Set failfast, if necessary
|
|
455
|
+
if result.shouldStop:
|
|
456
|
+
self.failfast.set()
|
|
457
|
+
|
|
458
|
+
# Return (test_count, errors, failures, skipped_count, expected_failure_count, unexpected_success_count)
|
|
459
|
+
return (
|
|
460
|
+
result.testsRun,
|
|
461
|
+
[self._format_error(result, error) for error in result.errors],
|
|
462
|
+
[self._format_error(result, failure) for failure in result.failures],
|
|
463
|
+
len(result.skipped),
|
|
464
|
+
len(result.expectedFailures),
|
|
465
|
+
len(result.unexpectedSuccesses),
|
|
466
|
+
result.test_record, # NVIDIA modification
|
|
467
|
+
)
|
|
468
|
+
|
|
469
|
+
@staticmethod
|
|
470
|
+
def _format_error(result, error):
|
|
471
|
+
return "\n".join(
|
|
472
|
+
[
|
|
473
|
+
unittest.TextTestResult.separator1,
|
|
474
|
+
result.getDescription(error[0]),
|
|
475
|
+
unittest.TextTestResult.separator2,
|
|
476
|
+
error[1],
|
|
477
|
+
]
|
|
478
|
+
)
|
|
479
|
+
|
|
480
|
+
|
|
481
|
+
class ParallelTextTestResult(unittest.TextTestResult):
|
|
482
|
+
def __init__(self, stream, descriptions, verbosity):
|
|
483
|
+
stream = type(stream)(sys.stderr)
|
|
484
|
+
super().__init__(stream, descriptions, verbosity)
|
|
485
|
+
self.test_record = [] # NVIDIA modification
|
|
486
|
+
|
|
487
|
+
def startTest(self, test):
|
|
488
|
+
if self.showAll:
|
|
489
|
+
self.stream.writeln(f"{self.getDescription(test)} ...")
|
|
490
|
+
self.stream.flush()
|
|
491
|
+
super(unittest.TextTestResult, self).startTest(test)
|
|
492
|
+
|
|
493
|
+
def _add_helper(self, test, dots_message, show_all_message):
|
|
494
|
+
if self.showAll:
|
|
495
|
+
self.stream.writeln(f"{self.getDescription(test)} ... {show_all_message}")
|
|
496
|
+
elif self.dots:
|
|
497
|
+
self.stream.write(dots_message)
|
|
498
|
+
self.stream.flush()
|
|
499
|
+
|
|
500
|
+
def addSuccess(self, test):
|
|
501
|
+
super(unittest.TextTestResult, self).addSuccess(test)
|
|
502
|
+
self._add_helper(test, ".", "ok")
|
|
503
|
+
|
|
504
|
+
def addError(self, test, err):
|
|
505
|
+
super(unittest.TextTestResult, self).addError(test, err)
|
|
506
|
+
self._add_helper(test, "E", "ERROR")
|
|
507
|
+
|
|
508
|
+
def addFailure(self, test, err):
|
|
509
|
+
super(unittest.TextTestResult, self).addFailure(test, err)
|
|
510
|
+
self._add_helper(test, "F", "FAIL")
|
|
511
|
+
|
|
512
|
+
def addSkip(self, test, reason):
|
|
513
|
+
super(unittest.TextTestResult, self).addSkip(test, reason)
|
|
514
|
+
self._add_helper(test, "s", f"skipped {reason!r}")
|
|
515
|
+
|
|
516
|
+
def addExpectedFailure(self, test, err):
|
|
517
|
+
super(unittest.TextTestResult, self).addExpectedFailure(test, err)
|
|
518
|
+
self._add_helper(test, "x", "expected failure")
|
|
519
|
+
|
|
520
|
+
def addUnexpectedSuccess(self, test):
|
|
521
|
+
super(unittest.TextTestResult, self).addUnexpectedSuccess(test)
|
|
522
|
+
self._add_helper(test, "u", "unexpected success")
|
|
523
|
+
|
|
524
|
+
def printErrors(self):
|
|
525
|
+
pass
|
|
526
|
+
|
|
527
|
+
|
|
528
|
+
def initialize_test_process(lock, shared_index, args, temp_dir):
|
|
529
|
+
"""Necessary operations to be executed at the start of every test process.
|
|
530
|
+
|
|
531
|
+
Currently this function can be used to set a separate Warp cache. (NVIDIA modification)
|
|
532
|
+
If the environment variable `WARP_CACHE_ROOT` is detected, the cache will be placed in the provided path.
|
|
533
|
+
|
|
534
|
+
It also ensures that Warp is initialized prior to running any tests.
|
|
535
|
+
"""
|
|
536
|
+
|
|
537
|
+
with lock:
|
|
538
|
+
shared_index.value += 1
|
|
539
|
+
worker_index = shared_index.value
|
|
540
|
+
|
|
541
|
+
with _coverage(args, temp_dir):
|
|
542
|
+
import warp as wp
|
|
543
|
+
|
|
544
|
+
if args.no_shared_cache:
|
|
545
|
+
from warp.thirdparty import appdirs
|
|
546
|
+
|
|
547
|
+
if "WARP_CACHE_ROOT" in os.environ:
|
|
548
|
+
cache_root_dir = os.path.join(os.getenv("WARP_CACHE_ROOT"), f"{wp.config.version}-{worker_index:03d}")
|
|
549
|
+
else:
|
|
550
|
+
cache_root_dir = appdirs.user_cache_dir(
|
|
551
|
+
appname="warp", appauthor="NVIDIA", version=f"{wp.config.version}-{worker_index:03d}"
|
|
552
|
+
)
|
|
553
|
+
|
|
554
|
+
wp.config.kernel_cache_dir = cache_root_dir
|
|
555
|
+
|
|
556
|
+
wp.build.clear_kernel_cache()
|
|
557
|
+
else:
|
|
558
|
+
# Initialize Warp is if hasn't been initialized already
|
|
559
|
+
wp.init()
|
|
560
|
+
|
|
561
|
+
|
|
562
|
+
if __name__ == "__main__": # pragma: no cover
|
|
563
|
+
main()
|