blob: bc32163fba528de463f7adce083839ddcbe2c5a5 [file] [log] [blame]
Sam Estep2e269762021-05-14 08:21:46 -07001#!/usr/bin/env python3
Peter Goldsborough53876c42018-03-09 13:02:02 -08002
3import argparse
Pritam Damania06d50b52020-10-22 10:53:07 -07004import copy
Shen Li10224432021-08-12 11:39:31 -07005from datetime import datetime
Eli Uriegas4982fc42021-08-16 15:30:24 -07006from distutils.util import strtobool
Nikita Shulga07767562021-12-14 09:23:21 -08007from distutils.version import LooseVersion
Rohan Varmaddc22ea2021-11-22 09:51:34 -08008import functools
Peter Goldsborough53876c42018-03-09 13:02:02 -08009import os
driazatiab5cf5a2021-08-25 12:58:24 -070010import pathlib
Peter Goldsborough53876c42018-03-09 13:02:02 -080011import shutil
Peter Goldsboroughc3f7e5f2018-04-10 11:31:23 -070012import signal
Peter Goldsborough53876c42018-03-09 13:02:02 -080013import subprocess
14import sys
15import tempfile
16
17import torch
Zsolt Dollensteinb0043072021-08-12 10:56:55 -070018from torch.utils import cpp_extension
driazati67d8e7b2021-08-25 11:19:49 -070019from torch.testing._internal.common_utils import (
20 FILE_SCHEMA,
21 IS_IN_CI,
22 TEST_WITH_ROCM,
23 shell,
24 set_cwd,
Alban Desmaison3d7abc02022-04-25 14:01:33 +000025 parser as common_parser,
driazati67d8e7b2021-08-25 11:19:49 -070026)
Shen Li10224432021-08-12 11:39:31 -070027import torch.distributed as dist
28from typing import Dict, Optional, List
Jane Xuc0adabe2021-03-05 13:34:17 -080029
driazatiab5cf5a2021-08-25 12:58:24 -070030REPO_ROOT = pathlib.Path(__file__).resolve().parent.parent
31
Jane Xuc0adabe2021-03-05 13:34:17 -080032try:
Rong Rong (AI Infra)718db962021-07-06 09:04:49 -070033 # using tools/ to optimize test run.
driazatiab5cf5a2021-08-25 12:58:24 -070034 sys.path.append(str(REPO_ROOT))
Rong Rong (AI Infra)718db962021-07-06 09:04:49 -070035 from tools.testing.test_selections import (
36 export_S3_test_times,
37 get_shard_based_on_S3,
Nikita Shulga01cfea92021-09-14 09:38:34 -070038 # NS: Disable target determination
39 # get_slow_tests_based_on_S3,
Rong Rong (AI Infra)718db962021-07-06 09:04:49 -070040 get_specified_test_cases,
Rong Rong (AI Infra)a5a10fe2021-07-12 11:20:12 -070041 get_reordered_tests,
42 get_test_case_configs,
Rong Rong (AI Infra)718db962021-07-06 09:04:49 -070043 )
Nikita Shulga01cfea92021-09-14 09:38:34 -070044 # NS: Disable target determination
45 # from tools.testing.modulefinder_determinator import (
46 # should_run_test,
47 # TARGET_DET_LIST,
48 # )
driazati67d8e7b2021-08-25 11:19:49 -070049
Rong Rong (AI Infra)718db962021-07-06 09:04:49 -070050 HAVE_TEST_SELECTION_TOOLS = True
Jane Xuc0adabe2021-03-05 13:34:17 -080051except ImportError:
Rong Rong (AI Infra)718db962021-07-06 09:04:49 -070052 HAVE_TEST_SELECTION_TOOLS = False
driazati67d8e7b2021-08-25 11:19:49 -070053 print(
54 "Unable to import test_selections from tools/testing. Running without test selection stats..."
55 )
Peter Goldsborough53876c42018-03-09 13:02:02 -080056
Jane Xuf30a7a22021-03-17 12:19:27 -070057
Nikita Shulgac2da1032021-08-31 17:19:11 -070058def discover_tests(
59 base_dir: Optional[pathlib.Path] = None,
60 blocklisted_patterns: Optional[List[str]] = None,
61 blocklisted_tests: Optional[List[str]] = None,
62 extra_tests: Optional[List[str]] = None) -> List[str]:
63 """
64 Searches for all python files starting with test_ excluding one specified by patterns
65 """
66 def skip_test_p(name: str) -> bool:
67 rc = False
68 if blocklisted_patterns is not None:
69 rc |= any(name.startswith(pattern) for pattern in blocklisted_patterns)
70 if blocklisted_tests is not None:
71 rc |= name in blocklisted_tests
72 return rc
73 cwd = pathlib.Path(__file__).resolve().parent if base_dir is None else base_dir
74 all_py_files = list(cwd.glob('**/test_*.py'))
75 rc = [str(fname.relative_to(cwd))[:-3] for fname in all_py_files]
76 # Invert slashes on Windows
77 if sys.platform == "win32":
78 rc = [name.replace('\\', '/') for name in rc]
79 rc = [test for test in rc if not skip_test_p(test)]
80 if extra_tests is not None:
81 rc += extra_tests
82 return sorted(rc)
83
Nikita Shulgac2da1032021-08-31 17:19:11 -070084TESTS = discover_tests(
85 blocklisted_patterns=[
86 'ao',
87 'bottleneck_test',
88 'custom_backend',
89 'custom_operator',
wushirong4d017892022-02-10 10:42:24 -080090 'fx', # executed by test_fx.py
Nikita Shulgac2da1032021-08-31 17:19:11 -070091 'jit', # executed by test_jit.py
92 'mobile',
93 'onnx',
94 'package', # executed by test_package.py
95 'quantization', # executed by test_quantization.py
Alban Desmaison701fa162022-03-01 11:15:30 -050096 'autograd', # executed by test_autograd.py
Nikita Shulgac2da1032021-08-31 17:19:11 -070097 ],
98 blocklisted_tests=[
99 'test_bundled_images',
100 'test_cpp_extensions_aot',
Nikita Shulga01cfea92021-09-14 09:38:34 -0700101 'test_determination',
Nikita Shulgac2da1032021-08-31 17:19:11 -0700102 'test_jit_fuser',
103 'test_jit_simple',
104 'test_jit_string',
105 'test_kernel_launch_checks',
106 'test_metal',
107 'test_nnapi',
Nikita Shulgac2da1032021-08-31 17:19:11 -0700108 'test_segment_reductions',
109 'test_static_runtime',
110 'test_throughput_benchmark',
111 'test_typing',
112 "distributed/algorithms/ddp_comm_hooks/test_ddp_hooks",
113 "distributed/algorithms/quantization/test_quantization",
114 "distributed/bin/test_script",
115 "distributed/elastic/multiprocessing/bin/test_script",
116 "distributed/launcher/bin/test_script",
117 "distributed/launcher/bin/test_script_init_method",
118 "distributed/launcher/bin/test_script_is_torchelastic_launched",
119 "distributed/launcher/bin/test_script_local_rank",
120 "distributed/test_c10d_spawn",
121 'distributions/test_transforms',
122 'distributions/test_utils',
123 ],
124 extra_tests=[
125 "test_cpp_extensions_aot_ninja",
126 "test_cpp_extensions_aot_no_ninja",
127 "distributed/elastic/timer/api_test",
128 "distributed/elastic/timer/local_timer_example",
129 "distributed/elastic/timer/local_timer_test",
130 "distributed/elastic/events/lib_test",
131 "distributed/elastic/metrics/api_test",
132 "distributed/elastic/utils/logging_test",
133 "distributed/elastic/utils/util_test",
134 "distributed/elastic/utils/distributed_test",
135 "distributed/elastic/multiprocessing/api_test",
Sahan Paliskara0bfa2f82022-03-17 05:12:14 -0700136 "test_deploy",
Nikita Shulgac2da1032021-08-31 17:19:11 -0700137 ]
138)
Pritam Damania06d50b52020-10-22 10:53:07 -0700139
Yanli Zhao61fca032021-10-07 09:05:05 -0700140FSDP_TEST = [test for test in TESTS if test.startswith("distributed/fsdp")]
141
Pritam Damania06d50b52020-10-22 10:53:07 -0700142# Tests need to be run with pytest.
143USE_PYTEST_LIST = [
driazati67d8e7b2021-08-25 11:19:49 -0700144 "distributed/pipeline/sync/skip/test_api",
145 "distributed/pipeline/sync/skip/test_gpipe",
146 "distributed/pipeline/sync/skip/test_inspect_skip_layout",
147 "distributed/pipeline/sync/skip/test_leak",
148 "distributed/pipeline/sync/skip/test_portal",
149 "distributed/pipeline/sync/skip/test_stash_pop",
150 "distributed/pipeline/sync/skip/test_tracker",
151 "distributed/pipeline/sync/skip/test_verify_skippables",
152 "distributed/pipeline/sync/test_balance",
153 "distributed/pipeline/sync/test_bugs",
154 "distributed/pipeline/sync/test_checkpoint",
155 "distributed/pipeline/sync/test_copy",
156 "distributed/pipeline/sync/test_deferred_batch_norm",
157 "distributed/pipeline/sync/test_dependency",
158 "distributed/pipeline/sync/test_inplace",
159 "distributed/pipeline/sync/test_microbatch",
160 "distributed/pipeline/sync/test_phony",
161 "distributed/pipeline/sync/test_pipe",
162 "distributed/pipeline/sync/test_pipeline",
163 "distributed/pipeline/sync/test_stream",
164 "distributed/pipeline/sync/test_transparency",
165 "distributed/pipeline/sync/test_worker",
166 "distributions/test_constraints",
167 "distributions/test_transforms",
168 "distributions/test_utils",
169 "test_typing",
Aliaksandr Ivanouec484982021-03-11 11:16:25 -0800170 "distributed/elastic/events/lib_test",
Aliaksandr Ivanou5c8ceef2021-04-29 06:11:18 -0700171 "distributed/elastic/agent/server/test/api_test",
Sahan Paliskara0bfa2f82022-03-17 05:12:14 -0700172 "test_deploy",
Peter Goldsborough53876c42018-03-09 13:02:02 -0800173]
Elias Ellison277cd742019-08-26 13:56:53 -0700174
Noman Arshad1a8269a2020-07-28 07:51:28 -0700175WINDOWS_BLOCKLIST = [
driazati67d8e7b2021-08-25 11:19:49 -0700176 "distributed/nn/jit/test_instantiator",
177 "distributed/rpc/test_faulty_agent",
178 "distributed/rpc/test_tensorpipe_agent",
179 "distributed/rpc/cuda/test_tensorpipe_agent",
180 "distributed/pipeline/sync/skip/test_api",
181 "distributed/pipeline/sync/skip/test_gpipe",
182 "distributed/pipeline/sync/skip/test_inspect_skip_layout",
183 "distributed/pipeline/sync/skip/test_leak",
184 "distributed/pipeline/sync/skip/test_portal",
185 "distributed/pipeline/sync/skip/test_stash_pop",
186 "distributed/pipeline/sync/skip/test_tracker",
187 "distributed/pipeline/sync/skip/test_verify_skippables",
188 "distributed/pipeline/sync/test_balance",
189 "distributed/pipeline/sync/test_bugs",
190 "distributed/pipeline/sync/test_checkpoint",
191 "distributed/pipeline/sync/test_copy",
192 "distributed/pipeline/sync/test_deferred_batch_norm",
193 "distributed/pipeline/sync/test_dependency",
194 "distributed/pipeline/sync/test_inplace",
195 "distributed/pipeline/sync/test_microbatch",
196 "distributed/pipeline/sync/test_phony",
197 "distributed/pipeline/sync/test_pipe",
198 "distributed/pipeline/sync/test_pipeline",
199 "distributed/pipeline/sync/test_stream",
200 "distributed/pipeline/sync/test_transparency",
201 "distributed/pipeline/sync/test_worker",
Aliaksandr Ivanou5c8ceef2021-04-29 06:11:18 -0700202 "distributed/elastic/agent/server/test/api_test",
driazati67d8e7b2021-08-25 11:19:49 -0700203 "distributed/elastic/multiprocessing/api_test",
pritam37eb3152022-05-21 22:33:58 +0000204 "distributed/_shard/checkpoint/test_checkpoint"
205 "distributed/_shard/checkpoint/test_file_system_checkpoint"
Pritam Damania64670e42022-02-01 22:53:18 -0800206 "distributed/_shard/sharding_spec/test_sharding_spec",
Wanchao Liang78ea86a2022-04-25 05:55:24 -0700207 "distributed/_shard/sharding_plan/test_sharding_plan",
Junjie Wang (PyTorch)88547392022-02-02 22:06:43 -0800208 "distributed/_shard/sharded_tensor/test_megatron_prototype",
Pritam Damania64670e42022-02-01 22:53:18 -0800209 "distributed/_shard/sharded_tensor/test_sharded_tensor",
Junjie Wang (PyTorch)19d0de82022-02-02 21:20:44 -0800210 "distributed/_shard/sharded_tensor/test_sharded_tensor_reshard",
Junjie Wang (PyTorch)7c44d562022-05-03 10:09:21 -0700211 "distributed/_shard/sharded_tensor/ops/test_chunk",
Junjie Wang (PyTorch)88547392022-02-02 22:06:43 -0800212 "distributed/_shard/sharded_tensor/ops/test_elementwise_ops",
Pritam Damania64670e42022-02-01 22:53:18 -0800213 "distributed/_shard/sharded_tensor/ops/test_embedding",
214 "distributed/_shard/sharded_tensor/ops/test_embedding_bag",
215 "distributed/_shard/sharded_tensor/ops/test_binary_cmp",
216 "distributed/_shard/sharded_tensor/ops/test_init",
217 "distributed/_shard/sharded_tensor/ops/test_linear",
wanchaolbe354d82022-04-11 14:56:45 -0700218 "distributed/_shard/sharded_tensor/ops/test_math_ops",
Junjie Wang (PyTorch)7c44d562022-05-03 10:09:21 -0700219 "distributed/_shard/sharded_tensor/ops/test_matrix_ops",
pritam9e52b502022-05-06 09:04:08 -0700220 "distributed/_shard/sharded_tensor/ops/test_softmax",
Pritam Damania64670e42022-02-01 22:53:18 -0800221 "distributed/_shard/sharded_optim/test_sharded_optim",
Junjie Wang (PyTorch)c1037d02022-04-27 23:17:28 -0700222 "distributed/_shard/test_partial_tensor",
Wanchao Liang0524b282022-03-24 05:36:04 -0700223 "distributed/_shard/test_replicated_tensor",
wushirong4d017892022-02-10 10:42:24 -0800224] + FSDP_TEST
Peter Goldsborough53876c42018-03-09 13:02:02 -0800225
Noman Arshad1a8269a2020-07-28 07:51:28 -0700226ROCM_BLOCKLIST = [
driazati67d8e7b2021-08-25 11:19:49 -0700227 "distributed/nn/jit/test_instantiator",
228 "distributed/rpc/test_faulty_agent",
229 "distributed/rpc/test_tensorpipe_agent",
230 "distributed/rpc/cuda/test_tensorpipe_agent",
pritam37eb3152022-05-21 22:33:58 +0000231 "distributed/_shard/checkpoint/test_checkpoint"
232 "distributed/_shard/checkpoint/test_file_system_checkpoint"
Wanchao Liang78ea86a2022-04-25 05:55:24 -0700233 "distributed/_shard/sharding_spec/test_sharding_spec",
234 "distributed/_shard/sharding_plan/test_sharding_plan",
Junjie Wang (PyTorch)88547392022-02-02 22:06:43 -0800235 "distributed/_shard/sharded_tensor/test_megatron_prototype",
Pritam Damania64670e42022-02-01 22:53:18 -0800236 "distributed/_shard/sharded_tensor/test_sharded_tensor",
Junjie Wang (PyTorch)19d0de82022-02-02 21:20:44 -0800237 "distributed/_shard/sharded_tensor/test_sharded_tensor_reshard",
Junjie Wang (PyTorch)7c44d562022-05-03 10:09:21 -0700238 "distributed/_shard/sharded_tensor/ops/test_chunk",
Junjie Wang (PyTorch)88547392022-02-02 22:06:43 -0800239 "distributed/_shard/sharded_tensor/ops/test_elementwise_ops",
Pritam Damania64670e42022-02-01 22:53:18 -0800240 "distributed/_shard/sharded_tensor/ops/test_embedding",
241 "distributed/_shard/sharded_tensor/ops/test_embedding_bag",
242 "distributed/_shard/sharded_tensor/ops/test_binary_cmp",
243 "distributed/_shard/sharded_tensor/ops/test_init",
244 "distributed/_shard/sharded_tensor/ops/test_linear",
wanchaolbe354d82022-04-11 14:56:45 -0700245 "distributed/_shard/sharded_tensor/ops/test_math_ops",
Junjie Wang (PyTorch)7c44d562022-05-03 10:09:21 -0700246 "distributed/_shard/sharded_tensor/ops/test_matrix_ops",
pritam9e52b502022-05-06 09:04:08 -0700247 "distributed/_shard/sharded_tensor/ops/test_softmax",
Pritam Damania64670e42022-02-01 22:53:18 -0800248 "distributed/_shard/sharded_optim/test_sharded_optim",
Junjie Wang (PyTorch)c1037d02022-04-27 23:17:28 -0700249 "distributed/_shard/test_partial_tensor",
Wanchao Liang0524b282022-03-24 05:36:04 -0700250 "distributed/_shard/test_replicated_tensor",
driazati67d8e7b2021-08-25 11:19:49 -0700251 "test_determination",
driazati67d8e7b2021-08-25 11:19:49 -0700252 "test_jit_legacy",
253 "test_type_hints",
254 "test_openmp",
Jeff Daily44bbb242022-04-22 19:50:36 +0000255]
iotamudeltaa38b5722018-08-06 14:48:45 -0700256
Noman Arshad1a8269a2020-07-28 07:51:28 -0700257RUN_PARALLEL_BLOCKLIST = [
driazati67d8e7b2021-08-25 11:19:49 -0700258 "test_cpp_extensions_jit",
259 "test_jit_disabled",
260 "test_mobile_optimizer",
261 "test_multiprocessing",
262 "test_multiprocessing_spawn",
263 "test_namedtuple_return_api",
264 "test_overrides",
265 "test_show_pickle",
266 "test_tensorexpr",
267 "test_cuda_primary_ctx",
Yanli Zhao61fca032021-10-07 09:05:05 -0700268] + FSDP_TEST
Nikita Shulga72e5b7a2020-05-06 22:08:45 -0700269
driazati67d8e7b2021-08-25 11:19:49 -0700270WINDOWS_COVERAGE_BLOCKLIST = []
petera1b1d0cd2021-01-19 14:57:07 -0800271
Jane Xu1354ee42021-08-26 09:27:47 -0700272# A subset of our TEST list that validates PyTorch's ops, modules, and autograd function as expected
273CORE_TEST_LIST = [
274 "test_autograd",
275 "test_modules",
276 "test_nn",
277 "test_ops",
atalmanebca80e2022-03-17 02:07:50 +0000278 "test_ops_gradients",
279 "test_ops_jit",
Jane Xu1354ee42021-08-26 09:27:47 -0700280 "test_torch"
281]
Neeraj Pradhanfaa9c222020-10-13 10:54:18 -0700282
Jane Xu0645e2b2021-03-18 13:19:39 -0700283# the JSON file to store the S3 test stats
driazati67d8e7b2021-08-25 11:19:49 -0700284TEST_TIMES_FILE = ".pytorch-test-times.json"
Jane Xu0645e2b2021-03-18 13:19:39 -0700285
Jane Xubcbe0722021-03-10 09:33:02 -0800286# if a test file takes longer than 5 min, we add it to TARGET_DET_LIST
287SLOW_TEST_THRESHOLD = 300
288
Pieter Noordhuise4cd8072019-09-11 02:17:48 -0700289DISTRIBUTED_TESTS_CONFIG = {}
Teng Li56539f52018-08-29 12:54:55 -0700290
291
Teng Li0988bba2018-09-10 23:21:36 -0700292if dist.is_available():
driazati67d8e7b2021-08-25 11:19:49 -0700293 DISTRIBUTED_TESTS_CONFIG["test"] = {"WORLD_SIZE": "1"}
Jithun Nair3c4cec52020-02-10 12:36:56 -0800294 if not TEST_WITH_ROCM and dist.is_mpi_available():
driazati67d8e7b2021-08-25 11:19:49 -0700295 DISTRIBUTED_TESTS_CONFIG["mpi"] = {
296 "WORLD_SIZE": "3",
297 "TEST_REPORT_SOURCE_OVERRIDE": "dist-mpi",
Teng Li56539f52018-08-29 12:54:55 -0700298 }
Teng Li0988bba2018-09-10 23:21:36 -0700299 if dist.is_nccl_available():
driazati67d8e7b2021-08-25 11:19:49 -0700300 DISTRIBUTED_TESTS_CONFIG["nccl"] = {
301 "WORLD_SIZE": "2" if torch.cuda.device_count() == 2 else "3",
302 "TEST_REPORT_SOURCE_OVERRIDE": "dist-nccl",
Teng Li56539f52018-08-29 12:54:55 -0700303 }
Jithun Nairf1c98562020-11-25 19:50:30 -0800304 if dist.is_gloo_available():
driazati67d8e7b2021-08-25 11:19:49 -0700305 DISTRIBUTED_TESTS_CONFIG["gloo"] = {
306 "WORLD_SIZE": "2" if torch.cuda.device_count() == 2 else "3",
307 "TEST_REPORT_SOURCE_OVERRIDE": "dist-gloo",
Pieter Noordhuise4cd8072019-09-11 02:17:48 -0700308 }
Teng Li56539f52018-08-29 12:54:55 -0700309
Peter Goldsboroughc3f7e5f2018-04-10 11:31:23 -0700310# https://stackoverflow.com/questions/2549939/get-signal-names-from-numbers-in-python
driazati67d8e7b2021-08-25 11:19:49 -0700311SIGNALS_TO_NAMES_DICT = {
312 getattr(signal, n): n for n in dir(signal) if n.startswith("SIG") and "_" not in n
313}
Peter Goldsboroughc3f7e5f2018-04-10 11:31:23 -0700314
Peter Goldsborough7978ba42018-11-07 14:27:06 -0800315CPP_EXTENSIONS_ERROR = """
Richard Zou62094122020-02-05 18:44:19 -0800316Ninja (https://ninja-build.org) is required for some of the C++ extensions
317tests, but it could not be found. Install ninja with `pip install ninja`
318or `conda install ninja`. Alternatively, disable said tests with
ashish616beb12020-02-21 12:07:51 -0800319`run_test.py --exclude test_cpp_extensions_aot_ninja test_cpp_extensions_jit`.
Peter Goldsborough7978ba42018-11-07 14:27:06 -0800320"""
321
Nikita Shulga1bda5e42020-08-26 16:14:17 -0700322PYTORCH_COLLECT_COVERAGE = bool(os.environ.get("PYTORCH_COLLECT_COVERAGE"))
Peter Goldsborough53876c42018-03-09 13:02:02 -0800323
driazati67d8e7b2021-08-25 11:19:49 -0700324ENABLE_PR_HISTORY_REORDERING = bool(
325 os.environ.get("ENABLE_PR_HISTORY_REORDERING", "0") == "1"
326)
Rong Rong (AI Infra)b2fc6de2021-06-16 13:31:14 -0700327
Jane Xu8bc0c752020-10-06 07:11:37 -0700328JIT_EXECUTOR_TESTS = [
driazati67d8e7b2021-08-25 11:19:49 -0700329 "test_jit_profiling",
330 "test_jit_legacy",
331 "test_jit_fuser_legacy",
Jane Xuba78eb82020-10-12 11:56:17 -0700332]
Jane Xu8bc0c752020-10-06 07:11:37 -0700333
Alban Desmaisonf275b3f2022-03-01 11:15:30 -0500334DISTRIBUTED_TESTS = [test for test in TESTS if test.startswith("distributed")]
Rong Rong (AI Infra)f4aff3a2021-08-24 08:01:36 -0700335
Ilya Persky1b089292022-02-15 08:33:59 -0800336TESTS_REQUIRING_LAPACK = [
337 "distributions/test_constraints",
338 "distributions/test_distributions",
339]
340
Jane Xu97dfc7e2021-06-08 15:59:32 -0700341# Dictionary matching test modules (in TESTS) to lists of test cases (within that test_module) that would be run when
342# options.run_specified_test_cases is enabled.
343# For example:
344# {
345# "test_nn": ["test_doubletensor_avg_pool3d", "test_share_memory", "test_hook_requires_grad"],
346# ...
347# }
Rong Ronge41bc312021-06-11 13:56:06 -0700348# then for test_nn.py, we would ONLY run test_doubletensor_avg_pool3d, test_share_memory, and test_hook_requires_grad.
Jane Xu97dfc7e2021-06-08 15:59:32 -0700349SPECIFIED_TEST_CASES_DICT: Dict[str, List[str]] = {}
350
351# The file from which the SPECIFIED_TEST_CASES_DICT will be filled, a CSV of test cases that would be run when
352# options.run_specified_test_cases is enabled.
driazati67d8e7b2021-08-25 11:19:49 -0700353SPECIFIED_TEST_CASES_FILE: str = ".pytorch_specified_test_cases.csv"
Jane Xu97dfc7e2021-06-08 15:59:32 -0700354
355
Peter Goldsborough4613eef2018-03-14 22:12:51 -0700356def print_to_stderr(message):
Peter Goldsborough4613eef2018-03-14 22:12:51 -0700357 print(message, file=sys.stderr)
358
359
Jane Xu97dfc7e2021-06-08 15:59:32 -0700360def get_test_case_args(test_module, using_pytest) -> List[str]:
Jane Xu97dfc7e2021-06-08 15:59:32 -0700361 args = []
Rong Ronge41bc312021-06-11 13:56:06 -0700362 # if test_module not specified or specified with '__all__' then run all tests
driazati67d8e7b2021-08-25 11:19:49 -0700363 if (
364 test_module not in SPECIFIED_TEST_CASES_DICT
365 or "__all__" in SPECIFIED_TEST_CASES_DICT[test_module]
366 ):
Rong Ronge41bc312021-06-11 13:56:06 -0700367 return args
Jane Xu97dfc7e2021-06-08 15:59:32 -0700368
369 if using_pytest:
driazati67d8e7b2021-08-25 11:19:49 -0700370 args.append("-k")
371 args.append(" or ".join(SPECIFIED_TEST_CASES_DICT[test_module]))
Jane Xu97dfc7e2021-06-08 15:59:32 -0700372 else:
373 for test in SPECIFIED_TEST_CASES_DICT[test_module]:
driazati67d8e7b2021-08-25 11:19:49 -0700374 args.append("-k")
Jane Xu97dfc7e2021-06-08 15:59:32 -0700375 args.append(test)
376
377 return args
378
379
petera1b1d0cd2021-01-19 14:57:07 -0800380def get_executable_command(options, allow_pytest, disable_coverage=False):
381 if options.coverage and not disable_coverage:
driazati67d8e7b2021-08-25 11:19:49 -0700382 executable = ["coverage", "run", "--parallel-mode", "--source=torch"]
Alexander Grund86492412020-07-28 08:12:41 -0700383 else:
384 executable = [sys.executable]
385 if options.pytest:
386 if allow_pytest:
driazati67d8e7b2021-08-25 11:19:49 -0700387 executable += ["-m", "pytest"]
Alexander Grund86492412020-07-28 08:12:41 -0700388 else:
driazati67d8e7b2021-08-25 11:19:49 -0700389 print_to_stderr(
390 "Pytest cannot be used for this test. Falling back to unittest."
391 )
Alexander Grund86492412020-07-28 08:12:41 -0700392 return executable
393
394
driazati67d8e7b2021-08-25 11:19:49 -0700395def run_test(
396 test_module, test_directory, options, launcher_cmd=None, extra_unittest_args=None
397):
Nikita Shulgafc510472020-09-09 15:07:27 -0700398 unittest_args = options.additional_unittest_args.copy()
Tongzhou Wang0d5e4a22018-09-03 19:55:58 -0700399 if options.verbose:
Sam Estepc4a6df92020-11-19 07:57:09 -0800400 unittest_args.append(f'-{"v"*options.verbose}') # in case of pytest
Noman Arshad1a8269a2020-07-28 07:51:28 -0700401 if test_module in RUN_PARALLEL_BLOCKLIST:
driazati67d8e7b2021-08-25 11:19:49 -0700402 unittest_args = [
403 arg for arg in unittest_args if not arg.startswith("--run-parallel")
404 ]
Alexander Grund86492412020-07-28 08:12:41 -0700405 if extra_unittest_args:
406 assert isinstance(extra_unittest_args, list)
407 unittest_args.extend(extra_unittest_args)
Pritam Damania78de12f2020-10-29 15:18:05 -0700408
409 # If using pytest, replace -f with equivalent -x
410 if options.pytest:
driazati67d8e7b2021-08-25 11:19:49 -0700411 unittest_args = [arg if arg != "-f" else "-x" for arg in unittest_args]
Rong Rong (AI Infra)a5a10fe2021-07-12 11:20:12 -0700412 elif IS_IN_CI:
413 # use the downloaded test cases configuration, not supported in pytest
driazati67d8e7b2021-08-25 11:19:49 -0700414 unittest_args.extend(["--import-slow-tests", "--import-disabled-tests"])
Pritam Damania78de12f2020-10-29 15:18:05 -0700415
petera1b1d0cd2021-01-19 14:57:07 -0800416 # Multiprocessing related tests cannot run with coverage.
lixinyu5ed0ad42021-01-28 17:42:22 -0800417 # Tracking issue: https://github.com/pytorch/pytorch/issues/50661
driazati67d8e7b2021-08-25 11:19:49 -0700418 disable_coverage = (
419 sys.platform == "win32" and test_module in WINDOWS_COVERAGE_BLOCKLIST
420 )
petera1b1d0cd2021-01-19 14:57:07 -0800421
Alexander Grund86492412020-07-28 08:12:41 -0700422 # Extra arguments are not supported with pytest
driazati67d8e7b2021-08-25 11:19:49 -0700423 executable = get_executable_command(
424 options, allow_pytest=not extra_unittest_args, disable_coverage=disable_coverage
425 )
Alexander Grund86492412020-07-28 08:12:41 -0700426
Rong Ronge41bc312021-06-11 13:56:06 -0700427 # TODO: move this logic into common_utils.py instead of passing in "-k" individually
Jane Xu97dfc7e2021-06-08 15:59:32 -0700428 # The following logic for running specified tests will only run for non-distributed tests, as those are dispatched
429 # to test_distributed and not run_test (this function)
430 if options.run_specified_test_cases:
driazati67d8e7b2021-08-25 11:19:49 -0700431 unittest_args.extend(get_test_case_args(test_module, "pytest" in executable))
Jane Xu97dfc7e2021-06-08 15:59:32 -0700432
433 # Can't call `python -m unittest test_*` here because it doesn't run code
434 # in `if __name__ == '__main__': `. So call `python test_*.py` instead.
driazati67d8e7b2021-08-25 11:19:49 -0700435 argv = [test_module + ".py"] + unittest_args
Jane Xu97dfc7e2021-06-08 15:59:32 -0700436
Alexander Grund86492412020-07-28 08:12:41 -0700437 command = (launcher_cmd or []) + executable + argv
driazati67d8e7b2021-08-25 11:19:49 -0700438 print_to_stderr("Executing {} ... [{}]".format(command, datetime.now()))
Junjie Baief499cd2019-04-19 09:47:52 -0700439 return shell(command, test_directory)
Peter Goldsborough53876c42018-03-09 13:02:02 -0800440
441
Alexander Grund86492412020-07-28 08:12:41 -0700442def test_cuda_primary_ctx(test_module, test_directory, options):
driazati67d8e7b2021-08-25 11:19:49 -0700443 return run_test(
444 test_module, test_directory, options, extra_unittest_args=["--subprocess"]
445 )
SsnL8482efb2019-07-16 10:05:53 -0700446
Rohan Varmaddc22ea2021-11-22 09:51:34 -0800447run_test_with_subprocess = functools.partial(run_test, extra_unittest_args=["--subprocess"])
448
449
Rohan Varma9554ebe2021-11-22 09:51:34 -0800450def get_run_test_with_subprocess_fn():
451 return lambda test_module, test_directory, options: run_test_with_subprocess(test_module, test_directory, options)
452
453
Richard Zou62094122020-02-05 18:44:19 -0800454
Rong Rong (AI Infra)40d2fe12021-06-24 09:19:16 -0700455def _test_cpp_extensions_aot(test_directory, options, use_ninja):
Richard Zou62094122020-02-05 18:44:19 -0800456 if use_ninja:
457 try:
458 cpp_extension.verify_ninja_availability()
459 except RuntimeError:
460 print(CPP_EXTENSIONS_ERROR)
461 return 1
462
463 # Wipe the build folder, if it exists already
driazati67d8e7b2021-08-25 11:19:49 -0700464 cpp_extensions_test_dir = os.path.join(test_directory, "cpp_extensions")
465 cpp_extensions_test_build_dir = os.path.join(cpp_extensions_test_dir, "build")
Richard Zou62094122020-02-05 18:44:19 -0800466 if os.path.exists(cpp_extensions_test_build_dir):
467 shutil.rmtree(cpp_extensions_test_build_dir)
468
469 # Build the test cpp extensions modules
470 shell_env = os.environ.copy()
driazati67d8e7b2021-08-25 11:19:49 -0700471 shell_env["USE_NINJA"] = str(1 if use_ninja else 0)
472 cmd = [sys.executable, "setup.py", "install", "--root", "./install"]
Richard Zou62094122020-02-05 18:44:19 -0800473 return_code = shell(cmd, cwd=cpp_extensions_test_dir, env=shell_env)
Peter Goldsboroughc3f7e5f2018-04-10 11:31:23 -0700474 if return_code != 0:
475 return return_code
driazati67d8e7b2021-08-25 11:19:49 -0700476 if sys.platform != "win32":
477 return_code = shell(
478 cmd,
479 cwd=os.path.join(cpp_extensions_test_dir, "no_python_abi_suffix_test"),
480 env=shell_env,
481 )
Peter Goldsborough6f2307b2018-11-27 17:33:54 -0800482 if return_code != 0:
483 return return_code
Peter Goldsborough53876c42018-03-09 13:02:02 -0800484
Richard Zou62094122020-02-05 18:44:19 -0800485 # "install" the test modules and run tests
driazati67d8e7b2021-08-25 11:19:49 -0700486 python_path = os.environ.get("PYTHONPATH", "")
Rong Rong (AI Infra)40d2fe12021-06-24 09:19:16 -0700487 from shutil import copyfile
driazati67d8e7b2021-08-25 11:19:49 -0700488
489 test_module = "test_cpp_extensions_aot" + ("_ninja" if use_ninja else "_no_ninja")
490 copyfile(
491 test_directory + "/test_cpp_extensions_aot.py",
492 test_directory + "/" + test_module + ".py",
493 )
Peter Goldsborough64049042018-03-10 16:16:40 -0800494 try:
driazati67d8e7b2021-08-25 11:19:49 -0700495 cpp_extensions = os.path.join(test_directory, "cpp_extensions")
496 install_directory = ""
Francisco Massab240cc92018-04-29 18:10:03 +0200497 # install directory is the one that is named site-packages
driazati67d8e7b2021-08-25 11:19:49 -0700498 for root, directories, _ in os.walk(os.path.join(cpp_extensions, "install")):
Francisco Massab240cc92018-04-29 18:10:03 +0200499 for directory in directories:
driazati67d8e7b2021-08-25 11:19:49 -0700500 if "-packages" in directory:
Francisco Massab240cc92018-04-29 18:10:03 +0200501 install_directory = os.path.join(root, directory)
peterjc12363af8982018-04-03 01:53:25 +0800502
driazati67d8e7b2021-08-25 11:19:49 -0700503 assert install_directory, "install_directory must not be empty"
504 os.environ["PYTHONPATH"] = os.pathsep.join([install_directory, python_path])
Alexander Grund86492412020-07-28 08:12:41 -0700505 return run_test(test_module, test_directory, options)
Peter Goldsborough64049042018-03-10 16:16:40 -0800506 finally:
driazati67d8e7b2021-08-25 11:19:49 -0700507 os.environ["PYTHONPATH"] = python_path
508 if os.path.exists(test_directory + "/" + test_module + ".py"):
509 os.remove(test_directory + "/" + test_module + ".py")
Peter Goldsborough53876c42018-03-09 13:02:02 -0800510
511
Alexander Grund86492412020-07-28 08:12:41 -0700512def test_cpp_extensions_aot_ninja(test_module, test_directory, options):
Rong Rong (AI Infra)40d2fe12021-06-24 09:19:16 -0700513 return _test_cpp_extensions_aot(test_directory, options, use_ninja=True)
Richard Zou62094122020-02-05 18:44:19 -0800514
515
Alexander Grund86492412020-07-28 08:12:41 -0700516def test_cpp_extensions_aot_no_ninja(test_module, test_directory, options):
Rong Rong (AI Infra)40d2fe12021-06-24 09:19:16 -0700517 return _test_cpp_extensions_aot(test_directory, options, use_ninja=False)
Richard Zou62094122020-02-05 18:44:19 -0800518
519
Alexander Grund86492412020-07-28 08:12:41 -0700520def test_distributed(test_module, test_directory, options):
Nikita Shulgab5873542021-05-10 10:50:23 -0700521 # MPI tests are broken with Python-3.9
driazati67d8e7b2021-08-25 11:19:49 -0700522 mpi_available = subprocess.call(
523 "command -v mpiexec", shell=True
524 ) == 0 and sys.version_info < (3, 9)
Edward Z. Yang3f3b6862018-03-14 07:44:58 -0400525 if options.verbose and not mpi_available:
driazati67d8e7b2021-08-25 11:19:49 -0700526 print_to_stderr("MPI not available -- MPI backend tests will be skipped")
Teng Li56539f52018-08-29 12:54:55 -0700527 config = DISTRIBUTED_TESTS_CONFIG
Teng Li56539f52018-08-29 12:54:55 -0700528 for backend, env_vars in config.items():
driazati67d8e7b2021-08-25 11:19:49 -0700529 if sys.platform == "win32" and backend != "gloo":
gunandrose4uf07ac6a2020-09-25 12:35:42 -0700530 continue
driazati67d8e7b2021-08-25 11:19:49 -0700531 if backend == "mpi" and not mpi_available:
Peter Goldsborough53876c42018-03-09 13:02:02 -0800532 continue
Peter Goldsborough4613eef2018-03-14 22:12:51 -0700533 for with_init_file in {True, False}:
driazati67d8e7b2021-08-25 11:19:49 -0700534 if sys.platform == "win32" and not with_init_file:
gunandrose4uf07ac6a2020-09-25 12:35:42 -0700535 continue
Peter Goldsborough53876c42018-03-09 13:02:02 -0800536 tmp_dir = tempfile.mkdtemp()
Edward Z. Yang3f3b6862018-03-14 07:44:58 -0400537 if options.verbose:
Rohan Varmab22abbe2020-09-08 23:08:55 -0700538 init_str = "with {} init_method"
539 with_init = init_str.format("file" if with_init_file else "env")
Peter Goldsborough4613eef2018-03-14 22:12:51 -0700540 print_to_stderr(
driazati67d8e7b2021-08-25 11:19:49 -0700541 "Running distributed tests for the {} backend {}".format(
542 backend, with_init
543 )
544 )
Catherine Lee56ea57d2022-05-03 23:01:42 +0000545 old_environ = dict(os.environ)
driazati67d8e7b2021-08-25 11:19:49 -0700546 os.environ["TEMP_DIR"] = tmp_dir
547 os.environ["BACKEND"] = backend
548 os.environ["INIT_METHOD"] = "env://"
Peter Goldsborough53876c42018-03-09 13:02:02 -0800549 os.environ.update(env_vars)
Peter Goldsborough4613eef2018-03-14 22:12:51 -0700550 if with_init_file:
Pritam Damania2d671ca2021-08-20 12:09:49 -0700551 if test_module == "test_distributed_spawn":
driazati67d8e7b2021-08-25 11:19:49 -0700552 init_method = f"{FILE_SCHEMA}{tmp_dir}/"
Teng Li56539f52018-08-29 12:54:55 -0700553 else:
driazati67d8e7b2021-08-25 11:19:49 -0700554 init_method = f"{FILE_SCHEMA}{tmp_dir}/shared_init_file"
555 os.environ["INIT_METHOD"] = init_method
Peter Goldsborough53876c42018-03-09 13:02:02 -0800556 try:
driazati67d8e7b2021-08-25 11:19:49 -0700557 os.mkdir(os.path.join(tmp_dir, "barrier"))
558 os.mkdir(os.path.join(tmp_dir, "test_dir"))
559 if backend == "mpi":
Simeon Monovdc941822018-04-17 20:34:33 -0700560 # test mpiexec for --noprefix option
driazati67d8e7b2021-08-25 11:19:49 -0700561 with open(os.devnull, "w") as devnull:
562 allowrunasroot_opt = (
563 "--allow-run-as-root"
564 if subprocess.call(
565 'mpiexec --allow-run-as-root -n 1 bash -c ""',
566 shell=True,
567 stdout=devnull,
568 stderr=subprocess.STDOUT,
569 )
570 == 0
571 else ""
572 )
573 noprefix_opt = (
574 "--noprefix"
575 if subprocess.call(
576 f'mpiexec {allowrunasroot_opt} -n 1 --noprefix bash -c ""',
577 shell=True,
578 stdout=devnull,
579 stderr=subprocess.STDOUT,
580 )
581 == 0
582 else ""
583 )
Simeon Monovdc941822018-04-17 20:34:33 -0700584
driazati67d8e7b2021-08-25 11:19:49 -0700585 mpiexec = ["mpiexec", "-n", "3", noprefix_opt, allowrunasroot_opt]
Simeon Monovdc941822018-04-17 20:34:33 -0700586
driazati67d8e7b2021-08-25 11:19:49 -0700587 return_code = run_test(
588 test_module, test_directory, options, launcher_cmd=mpiexec
589 )
Peter Goldsboroughc3f7e5f2018-04-10 11:31:23 -0700590 else:
Rohan Varmaf02efc72021-11-11 06:09:11 -0800591 return_code = run_test(test_module, test_directory, options, extra_unittest_args=["--subprocess"])
Peter Goldsboroughc3f7e5f2018-04-10 11:31:23 -0700592 if return_code != 0:
593 return return_code
Peter Goldsborough53876c42018-03-09 13:02:02 -0800594 finally:
595 shutil.rmtree(tmp_dir)
Catherine Lee56ea57d2022-05-03 23:01:42 +0000596 os.environ.clear()
597 os.environ.update(old_environ)
Peter Goldsboroughc3f7e5f2018-04-10 11:31:23 -0700598 return 0
Peter Goldsborough53876c42018-03-09 13:02:02 -0800599
600
601CUSTOM_HANDLERS = {
driazati67d8e7b2021-08-25 11:19:49 -0700602 "test_cuda_primary_ctx": test_cuda_primary_ctx,
603 "test_cpp_extensions_aot_no_ninja": test_cpp_extensions_aot_no_ninja,
604 "test_cpp_extensions_aot_ninja": test_cpp_extensions_aot_ninja,
605 "distributed/test_distributed_spawn": test_distributed,
Rohan Varma9554ebe2021-11-22 09:51:34 -0800606 "distributed/test_c10d_nccl": get_run_test_with_subprocess_fn(),
607 "distributed/test_c10d_gloo": get_run_test_with_subprocess_fn(),
Rohan Varma3bd7dbf2021-11-29 10:56:20 -0800608 "distributed/test_c10d_common": get_run_test_with_subprocess_fn(),
609 "distributed/test_c10d_spawn_gloo": get_run_test_with_subprocess_fn(),
610 "distributed/test_c10d_spawn_nccl": get_run_test_with_subprocess_fn(),
611 "distributed/test_store": get_run_test_with_subprocess_fn(),
612 "distributed/test_pg_wrapper": get_run_test_with_subprocess_fn(),
Rohan Varma250d0bd2021-11-29 10:56:20 -0800613 "distributed/rpc/test_faulty_agent": get_run_test_with_subprocess_fn(),
614 "distributed/rpc/test_tensorpipe_agent": get_run_test_with_subprocess_fn(),
615 "distributed/rpc/cuda/test_tensorpipe_agent": get_run_test_with_subprocess_fn(),
Peter Goldsborough53876c42018-03-09 13:02:02 -0800616}
617
Simeon Monov24b49312018-04-16 11:33:50 -0700618def parse_test_module(test):
driazati67d8e7b2021-08-25 11:19:49 -0700619 return test.split(".")[0]
Simeon Monov24b49312018-04-16 11:33:50 -0700620
621
622class TestChoices(list):
623 def __init__(self, *args, **kwargs):
624 super(TestChoices, self).__init__(args[0])
625
626 def __contains__(self, item):
627 return list.__contains__(self, parse_test_module(item))
628
629
Peter Goldsborough53876c42018-03-09 13:02:02 -0800630def parse_args():
631 parser = argparse.ArgumentParser(
driazati67d8e7b2021-08-25 11:19:49 -0700632 description="Run the PyTorch unit test suite",
633 epilog="where TESTS is any of: {}".format(", ".join(TESTS)),
634 formatter_class=argparse.RawTextHelpFormatter,
Alban Desmaison3d7abc02022-04-25 14:01:33 +0000635 parents=[common_parser]
driazati67d8e7b2021-08-25 11:19:49 -0700636 )
Peter Goldsborough53876c42018-03-09 13:02:02 -0800637 parser.add_argument(
driazati67d8e7b2021-08-25 11:19:49 -0700638 "-v",
639 "--verbose",
640 action="count",
Sam Estepc4a6df92020-11-19 07:57:09 -0800641 default=0,
driazati67d8e7b2021-08-25 11:19:49 -0700642 help="print verbose information and test-by-test results",
643 )
644 parser.add_argument("--jit", "--jit", action="store_true", help="run all jit tests")
Peter Goldsborough53876c42018-03-09 13:02:02 -0800645 parser.add_argument(
driazati67d8e7b2021-08-25 11:19:49 -0700646 "--distributed-tests",
647 "--distributed-tests",
648 action="store_true",
649 help="run all distributed tests",
650 )
Elias Ellisonf6e58462019-05-30 14:03:31 -0700651 parser.add_argument(
Jane Xu1354ee42021-08-26 09:27:47 -0700652 "-core",
653 "--core",
654 action="store_true",
655 help="Only run core tests, or tests that validate PyTorch's ops, modules,"
656 "and autograd. They are defined by CORE_TEST_LIST."
657 )
658 parser.add_argument(
driazati67d8e7b2021-08-25 11:19:49 -0700659 "-pt",
660 "--pytest",
661 action="store_true",
662 help="If true, use `pytest` to execute the tests. E.g., this runs "
663 "TestTorch with pytest in verbose and coverage mode: "
664 "python run_test.py -vci torch -pt",
665 )
Rong Rong (AI Infra)f4aff3a2021-08-24 08:01:36 -0700666 parser.add_argument(
driazati67d8e7b2021-08-25 11:19:49 -0700667 "-c",
668 "--coverage",
669 action="store_true",
670 help="enable coverage",
671 default=PYTORCH_COLLECT_COVERAGE,
672 )
Peter Goldsborough53876c42018-03-09 13:02:02 -0800673 parser.add_argument(
driazati67d8e7b2021-08-25 11:19:49 -0700674 "-i",
675 "--include",
676 nargs="+",
Simeon Monov24b49312018-04-16 11:33:50 -0700677 choices=TestChoices(TESTS),
Peter Goldsborough53876c42018-03-09 13:02:02 -0800678 default=TESTS,
driazati67d8e7b2021-08-25 11:19:49 -0700679 metavar="TESTS",
680 help="select a set of tests to include (defaults to ALL tests)."
681 " tests must be a part of the TESTS list defined in run_test.py",
682 )
Peter Goldsborough53876c42018-03-09 13:02:02 -0800683 parser.add_argument(
driazati67d8e7b2021-08-25 11:19:49 -0700684 "-x",
685 "--exclude",
686 nargs="+",
Peter Goldsborough53876c42018-03-09 13:02:02 -0800687 choices=TESTS,
driazati67d8e7b2021-08-25 11:19:49 -0700688 metavar="TESTS",
Peter Goldsborough53876c42018-03-09 13:02:02 -0800689 default=[],
driazati67d8e7b2021-08-25 11:19:49 -0700690 help="select a set of tests to exclude",
691 )
Peter Goldsborough53876c42018-03-09 13:02:02 -0800692 parser.add_argument(
driazati67d8e7b2021-08-25 11:19:49 -0700693 "-f",
694 "--first",
Peter Goldsborough53876c42018-03-09 13:02:02 -0800695 choices=TESTS,
driazati67d8e7b2021-08-25 11:19:49 -0700696 metavar="TESTS",
697 help="select the test to start from (excludes previous tests)",
698 )
Peter Goldsborough53876c42018-03-09 13:02:02 -0800699 parser.add_argument(
driazati67d8e7b2021-08-25 11:19:49 -0700700 "-l",
701 "--last",
Peter Goldsborough53876c42018-03-09 13:02:02 -0800702 choices=TESTS,
driazati67d8e7b2021-08-25 11:19:49 -0700703 metavar="TESTS",
704 help="select the last test to run (excludes following tests)",
705 )
Peter Goldsborough53876c42018-03-09 13:02:02 -0800706 parser.add_argument(
driazati67d8e7b2021-08-25 11:19:49 -0700707 "--bring-to-front",
708 nargs="+",
James Reed75977412019-08-14 18:06:14 -0700709 choices=TestChoices(TESTS),
710 default=[],
driazati67d8e7b2021-08-25 11:19:49 -0700711 metavar="TESTS",
712 help="select a set of tests to run first. This can be used in situations"
713 " where you want to run all tests, but care more about some set, "
714 "e.g. after making a change to a specific component",
715 )
James Reed75977412019-08-14 18:06:14 -0700716 parser.add_argument(
driazati67d8e7b2021-08-25 11:19:49 -0700717 "--ignore-win-blocklist",
718 action="store_true",
719 help="always run blocklisted windows tests",
720 )
Nikita Shulgab5b62b32021-11-23 18:44:14 -0800721 # NS: Disable target determination until it can be made more reliable
722 # parser.add_argument(
723 # "--determine-from",
724 # help="File of affected source filenames to determine which tests to run.",
725 # )
Yunus Rahbar7cee7872020-03-03 17:29:14 -0800726 parser.add_argument(
driazati67d8e7b2021-08-25 11:19:49 -0700727 "--continue-through-error",
728 action="store_true",
729 help="Runs the full test suite despite one of the tests failing",
730 default=strtobool(os.environ.get("CONTINUE_THROUGH_ERROR", "False")),
731 )
Eli Uriegasf71cccc2020-07-08 17:24:06 -0700732 parser.add_argument(
driazati67d8e7b2021-08-25 11:19:49 -0700733 "additional_unittest_args",
734 nargs="*",
735 help="additional arguments passed through to unittest, e.g., "
736 "python run_test.py -i sparse -- TestSparse.test_factory_size_check",
737 )
Jane (Yuan) Xu6acd7b62020-10-02 11:10:12 -0700738 parser.add_argument(
driazati67d8e7b2021-08-25 11:19:49 -0700739 "--export-past-test-times",
740 nargs="?",
Jane Xuf30a7a22021-03-17 12:19:27 -0700741 type=str,
Jane Xu0645e2b2021-03-18 13:19:39 -0700742 const=TEST_TIMES_FILE,
driazati67d8e7b2021-08-25 11:19:49 -0700743 help="dumps test times from previous S3 stats into a file, format JSON",
Jane Xuf30a7a22021-03-17 12:19:27 -0700744 )
745 parser.add_argument(
driazati67d8e7b2021-08-25 11:19:49 -0700746 "--shard",
Jane (Yuan) Xu6acd7b62020-10-02 11:10:12 -0700747 nargs=2,
748 type=int,
driazati67d8e7b2021-08-25 11:19:49 -0700749 help="runs a shard of the tests (taking into account other selections), e.g., "
750 "--shard 2 3 will break up the selected tests into 3 shards and run the tests "
751 "in the 2nd shard (the first number should not exceed the second)",
Jane (Yuan) Xu6acd7b62020-10-02 11:10:12 -0700752 )
Jane Xu8bc0c752020-10-06 07:11:37 -0700753 parser.add_argument(
driazati67d8e7b2021-08-25 11:19:49 -0700754 "--exclude-jit-executor",
755 action="store_true",
756 help="exclude tests that are run for a specific jit config",
Jane Xu8bc0c752020-10-06 07:11:37 -0700757 )
Jane Xu97dfc7e2021-06-08 15:59:32 -0700758 parser.add_argument(
driazati67d8e7b2021-08-25 11:19:49 -0700759 "--exclude-distributed-tests",
760 action="store_true",
761 help="exclude distributed tests",
Rong Rong (AI Infra)f4aff3a2021-08-24 08:01:36 -0700762 )
763 parser.add_argument(
driazati67d8e7b2021-08-25 11:19:49 -0700764 "--run-specified-test-cases",
765 nargs="?",
Jane Xu97dfc7e2021-06-08 15:59:32 -0700766 type=str,
767 const=SPECIFIED_TEST_CASES_FILE,
driazati67d8e7b2021-08-25 11:19:49 -0700768 help="load specified test cases file dumped from previous OSS CI stats, format CSV. "
769 " If all test cases should run for a <test_module> please add a single row: \n"
770 " test_filename,test_case_name\n"
771 " ...\n"
772 " <test_module>,__all__\n"
773 " ...\n"
774 'how we use the stats will be based on option "--use-specified-test-cases-by".',
Rong Ronge41bc312021-06-11 13:56:06 -0700775 )
776 parser.add_argument(
driazati67d8e7b2021-08-25 11:19:49 -0700777 "--use-specified-test-cases-by",
Rong Ronge41bc312021-06-11 13:56:06 -0700778 type=str,
driazati67d8e7b2021-08-25 11:19:49 -0700779 choices=["include", "bring-to-front"],
780 default="include",
Rong Ronge41bc312021-06-11 13:56:06 -0700781 help='used together with option "--run-specified-test-cases". When specified test case '
driazati67d8e7b2021-08-25 11:19:49 -0700782 "file is set, this option allows the user to control whether to only run the specified test "
783 "modules or to simply bring the specified modules to front and also run the remaining "
784 "modules. Note: regardless of this option, we will only run the specified test cases "
785 " within a specified test module. For unspecified test modules with the bring-to-front "
786 "option, all test cases will be run, as one may expect.",
Jane Xu97dfc7e2021-06-08 15:59:32 -0700787 )
Alban Desmaison7e919bd2022-02-22 09:52:11 -0500788 parser.add_argument(
789 "--dry-run",
790 action="store_true",
791 help="Only list the test that will run.",
792 )
Peter Goldsborough53876c42018-03-09 13:02:02 -0800793 return parser.parse_args()
794
795
Simeon Monov24b49312018-04-16 11:33:50 -0700796def find_test_index(test, selected_tests, find_last_index=False):
SsnLffd61382019-01-16 22:56:56 -0800797 """Find the index of the first or last occurrence of a given test/test module in the list of selected tests.
Simeon Monov24b49312018-04-16 11:33:50 -0700798
SsnLffd61382019-01-16 22:56:56 -0800799 This function is used to determine the indices when slicing the list of selected tests when
Simeon Monov24b49312018-04-16 11:33:50 -0700800 ``options.first``(:attr:`find_last_index`=False) and/or ``options.last``(:attr:`find_last_index`=True) are used.
801
802 :attr:`selected_tests` can be a list that contains multiple consequent occurrences of tests
803 as part of the same test module, e.g.:
804
805 ```
806 selected_tests = ['autograd', 'cuda', **'torch.TestTorch.test_acos',
807 'torch.TestTorch.test_tan', 'torch.TestTorch.test_add'**, 'utils']
808 ```
809
Tongzhou Wang0d5e4a22018-09-03 19:55:58 -0700810 If :attr:`test`='torch' and :attr:`find_last_index`=False, result should be **2**.
811 If :attr:`test`='torch' and :attr:`find_last_index`=True, result should be **4**.
Simeon Monov24b49312018-04-16 11:33:50 -0700812
Samuel Markse6779d42020-12-28 09:33:01 -0800813 Args:
Simeon Monov24b49312018-04-16 11:33:50 -0700814 test (str): Name of test to lookup
815 selected_tests (list): List of tests
816 find_last_index (bool, optional): should we lookup the index of first or last
817 occurrence (first is default)
818
819 Returns:
Brian Wignalle7fe64f2019-12-02 20:15:54 -0800820 index of the first or last occurrence of the given test
Simeon Monov24b49312018-04-16 11:33:50 -0700821 """
822 idx = 0
823 found_idx = -1
824 for t in selected_tests:
825 if t.startswith(test):
826 found_idx = idx
827 if not find_last_index:
828 break
829 idx += 1
830 return found_idx
831
832
833def exclude_tests(exclude_list, selected_tests, exclude_message=None):
Simeon Monov24b49312018-04-16 11:33:50 -0700834 for exclude_test in exclude_list:
Richard Zou62094122020-02-05 18:44:19 -0800835 tests_copy = selected_tests[:]
Simeon Monov24b49312018-04-16 11:33:50 -0700836 for test in tests_copy:
837 if test.startswith(exclude_test):
838 if exclude_message is not None:
driazati67d8e7b2021-08-25 11:19:49 -0700839 print_to_stderr("Excluding {} {}".format(test, exclude_message))
Simeon Monov24b49312018-04-16 11:33:50 -0700840 selected_tests.remove(test)
841 return selected_tests
842
843
Peter Goldsborough53876c42018-03-09 13:02:02 -0800844def get_selected_tests(options):
Rong Rong (AI Infra)f4aff3a2021-08-24 08:01:36 -0700845 # First make sure run specific test cases options are processed.
Rong Ronge41bc312021-06-11 13:56:06 -0700846 if options.run_specified_test_cases:
driazati67d8e7b2021-08-25 11:19:49 -0700847 if options.use_specified_test_cases_by == "include":
Rong Ronge41bc312021-06-11 13:56:06 -0700848 options.include = list(SPECIFIED_TEST_CASES_DICT.keys())
driazati67d8e7b2021-08-25 11:19:49 -0700849 elif options.use_specified_test_cases_by == "bring-to-front":
Rong Ronge41bc312021-06-11 13:56:06 -0700850 options.bring_to_front = list(SPECIFIED_TEST_CASES_DICT.keys())
851
Peter Goldsborough53876c42018-03-09 13:02:02 -0800852 selected_tests = options.include
Peter Goldsborough53876c42018-03-09 13:02:02 -0800853
Rong Rong (AI Infra)f4aff3a2021-08-24 08:01:36 -0700854 # filter if there's JIT only and distributed only test options
855 if options.jit:
856 selected_tests = list(
driazati67d8e7b2021-08-25 11:19:49 -0700857 filter(lambda test_name: "jit" in test_name, selected_tests)
858 )
Rong Rong (AI Infra)f4aff3a2021-08-24 08:01:36 -0700859
860 if options.distributed_tests:
861 selected_tests = list(
driazati67d8e7b2021-08-25 11:19:49 -0700862 filter(lambda test_name: test_name in DISTRIBUTED_TESTS, selected_tests)
863 )
Rong Rong (AI Infra)f4aff3a2021-08-24 08:01:36 -0700864
Jane Xu1354ee42021-08-26 09:27:47 -0700865 # Filter to only run core tests when --core option is specified
866 if options.core:
867 selected_tests = list(
868 filter(lambda test_name: test_name in CORE_TEST_LIST, selected_tests)
869 )
870
Rong Rong (AI Infra)f4aff3a2021-08-24 08:01:36 -0700871 # process reordering
James Reed75977412019-08-14 18:06:14 -0700872 if options.bring_to_front:
873 to_front = set(options.bring_to_front)
driazati67d8e7b2021-08-25 11:19:49 -0700874 selected_tests = options.bring_to_front + list(
875 filter(lambda name: name not in to_front, selected_tests)
876 )
James Reed75977412019-08-14 18:06:14 -0700877
Peter Goldsborough53876c42018-03-09 13:02:02 -0800878 if options.first:
Simeon Monov24b49312018-04-16 11:33:50 -0700879 first_index = find_test_index(options.first, selected_tests)
Peter Goldsborough53876c42018-03-09 13:02:02 -0800880 selected_tests = selected_tests[first_index:]
881
882 if options.last:
Simeon Monov24b49312018-04-16 11:33:50 -0700883 last_index = find_test_index(options.last, selected_tests, find_last_index=True)
driazati67d8e7b2021-08-25 11:19:49 -0700884 selected_tests = selected_tests[: last_index + 1]
Peter Goldsborough53876c42018-03-09 13:02:02 -0800885
Rong Rong (AI Infra)f4aff3a2021-08-24 08:01:36 -0700886 # process exclusion
Jane Xu8bc0c752020-10-06 07:11:37 -0700887 if options.exclude_jit_executor:
888 options.exclude.extend(JIT_EXECUTOR_TESTS)
889
Rong Rong (AI Infra)f4aff3a2021-08-24 08:01:36 -0700890 if options.exclude_distributed_tests:
891 options.exclude.extend(DISTRIBUTED_TESTS)
892
Andrey Talman622cff32022-04-07 15:37:09 -0700893 # these tests failing in CUDA 11.6 temporary disabling. issue https://github.com/pytorch/pytorch/issues/75375
894 if torch.version.cuda is not None and LooseVersion(torch.version.cuda) == "11.6":
895 options.exclude.extend(["distributions/test_constraints"])
896
Simeon Monov24b49312018-04-16 11:33:50 -0700897 selected_tests = exclude_tests(options.exclude, selected_tests)
898
driazati67d8e7b2021-08-25 11:19:49 -0700899 if sys.platform == "win32" and not options.ignore_win_blocklist:
900 target_arch = os.environ.get("VSCMD_ARG_TGT_ARCH")
901 if target_arch != "x64":
902 WINDOWS_BLOCKLIST.append("cpp_extensions_aot_no_ninja")
903 WINDOWS_BLOCKLIST.append("cpp_extensions_aot_ninja")
904 WINDOWS_BLOCKLIST.append("cpp_extensions_jit")
905 WINDOWS_BLOCKLIST.append("jit")
906 WINDOWS_BLOCKLIST.append("jit_fuser")
peterjc123d45f3d02018-04-12 18:12:39 +0800907
Ilya Perskybc514cb2022-01-06 08:53:50 -0800908 # This is exception that's caused by this issue https://github.com/pytorch/pytorch/issues/69460
Andrey Talman77a4b892021-12-13 20:47:33 -0800909 # This below code should be removed once this issue is solved
Nikita Shulga24ee1d12021-12-14 14:45:47 -0800910 if torch.version.cuda is not None and LooseVersion(torch.version.cuda) >= "11.5":
Andrey Talman77a4b892021-12-13 20:47:33 -0800911 WINDOWS_BLOCKLIST.append("test_cpp_extensions_aot")
912 WINDOWS_BLOCKLIST.append("test_cpp_extensions_aot_ninja")
913 WINDOWS_BLOCKLIST.append("test_cpp_extensions_aot_no_ninja")
914
driazati67d8e7b2021-08-25 11:19:49 -0700915 selected_tests = exclude_tests(WINDOWS_BLOCKLIST, selected_tests, "on Windows")
Peter Goldsborough53876c42018-03-09 13:02:02 -0800916
iotamudeltaa38b5722018-08-06 14:48:45 -0700917 elif TEST_WITH_ROCM:
driazati67d8e7b2021-08-25 11:19:49 -0700918 selected_tests = exclude_tests(ROCM_BLOCKLIST, selected_tests, "on ROCm")
iotamudeltaa38b5722018-08-06 14:48:45 -0700919
Rong Rong (AI Infra)f4aff3a2021-08-24 08:01:36 -0700920 # sharding
Jane Xucaf76c22021-06-07 15:03:19 -0700921 if options.shard:
922 assert len(options.shard) == 2, "Unexpected shard format"
923 assert min(options.shard) > 0, "Shards must be positive numbers"
924 which_shard, num_shards = options.shard
driazati67d8e7b2021-08-25 11:19:49 -0700925 assert (
926 which_shard <= num_shards
927 ), "Selected shard must be less than or equal to total number of shards"
928 assert num_shards <= len(
929 selected_tests
930 ), f"Number of shards must be less than {len(selected_tests)}"
Rong Rong (AI Infra)718db962021-07-06 09:04:49 -0700931 # TODO: fix this to use test_times_filename, but currently this is not working
932 # because setting the export arg immeidately halts the test execution.
driazati67d8e7b2021-08-25 11:19:49 -0700933 selected_tests = get_shard_based_on_S3(
934 which_shard, num_shards, selected_tests, TEST_TIMES_FILE
935 )
Jane Xucaf76c22021-06-07 15:03:19 -0700936
Ilya Perskybc514cb2022-01-06 08:53:50 -0800937 # skip all distributed tests if distributed package is not available.
938 if not dist.is_available():
939 selected_tests = exclude_tests(DISTRIBUTED_TESTS, selected_tests,
940 "PyTorch is built without distributed support.")
941
Ilya Persky1b089292022-02-15 08:33:59 -0800942 # skip tests that require LAPACK when it's not available
943 if not torch._C.has_lapack:
944 selected_tests = exclude_tests(TESTS_REQUIRING_LAPACK, selected_tests,
945 "PyTorch is built without LAPACK support.")
946
Peter Goldsborough53876c42018-03-09 13:02:02 -0800947 return selected_tests
948
949
Nikita Shulga1bda5e42020-08-26 16:14:17 -0700950def run_test_module(test: str, test_directory: str, options) -> Optional[str]:
951 test_module = parse_test_module(test)
952
953 # Printing the date here can help diagnose which tests are slow
driazati67d8e7b2021-08-25 11:19:49 -0700954 print_to_stderr("Running {} ... [{}]".format(test, datetime.now()))
Nikita Shulgab00cdfe2021-03-12 09:51:27 -0800955 handler = CUSTOM_HANDLERS.get(test_module, run_test)
Nikita Shulga1bda5e42020-08-26 16:14:17 -0700956 return_code = handler(test_module, test_directory, options)
957 assert isinstance(return_code, int) and not isinstance(
driazati67d8e7b2021-08-25 11:19:49 -0700958 return_code, bool
959 ), "Return code should be an integer"
Nikita Shulga1bda5e42020-08-26 16:14:17 -0700960 if return_code == 0:
961 return None
962
driazati67d8e7b2021-08-25 11:19:49 -0700963 message = f"{test} failed!"
Nikita Shulga1bda5e42020-08-26 16:14:17 -0700964 if return_code < 0:
965 # subprocess.Popen returns the child process' exit signal as
966 # return code -N, where N is the signal number.
967 signal_name = SIGNALS_TO_NAMES_DICT[-return_code]
driazati67d8e7b2021-08-25 11:19:49 -0700968 message += f" Received signal: {signal_name}"
Nikita Shulga1bda5e42020-08-26 16:14:17 -0700969 return message
970
driazati187a5242021-04-22 10:25:41 -0700971
Peter Goldsborough53876c42018-03-09 13:02:02 -0800972def main():
973 options = parse_args()
Jane Xuf30a7a22021-03-17 12:19:27 -0700974
Rong Rong (AI Infra)718db962021-07-06 09:04:49 -0700975 # TODO: move this export & download function in tools/ folder
Jane Xu0645e2b2021-03-18 13:19:39 -0700976 test_times_filename = options.export_past_test_times
Jane Xuf30a7a22021-03-17 12:19:27 -0700977 if test_times_filename:
driazati67d8e7b2021-08-25 11:19:49 -0700978 print(
979 f"Exporting past test times from S3 to {test_times_filename}, no tests will be run."
980 )
Rong Rong (AI Infra)718db962021-07-06 09:04:49 -0700981 export_S3_test_times(test_times_filename)
Jane Xuf30a7a22021-03-17 12:19:27 -0700982 return
983
Jane Xu97dfc7e2021-06-08 15:59:32 -0700984 specified_test_cases_filename = options.run_specified_test_cases
985 if specified_test_cases_filename:
driazati67d8e7b2021-08-25 11:19:49 -0700986 print(
987 f"Loading specified test cases to run from {specified_test_cases_filename}."
988 )
Rong Rong (AI Infra)718db962021-07-06 09:04:49 -0700989 global SPECIFIED_TEST_CASES_DICT
driazati67d8e7b2021-08-25 11:19:49 -0700990 SPECIFIED_TEST_CASES_DICT = get_specified_test_cases(
991 specified_test_cases_filename, TESTS
992 )
Jane Xu97dfc7e2021-06-08 15:59:32 -0700993
driazatiab5cf5a2021-08-25 12:58:24 -0700994 test_directory = str(REPO_ROOT / "test")
Peter Goldsborough53876c42018-03-09 13:02:02 -0800995 selected_tests = get_selected_tests(options)
Simeon Monov24b49312018-04-16 11:33:50 -0700996
Peter Goldsborough53876c42018-03-09 13:02:02 -0800997 if options.verbose:
Alban Desmaison7e919bd2022-02-22 09:52:11 -0500998 print_to_stderr("Selected tests:\n {}".format("\n ".join(selected_tests)))
999
1000 if options.dry_run:
1001 return
Peter Goldsborough53876c42018-03-09 13:02:02 -08001002
Nikita Shulga1bda5e42020-08-26 16:14:17 -07001003 if options.coverage and not PYTORCH_COLLECT_COVERAGE:
driazati67d8e7b2021-08-25 11:19:49 -07001004 shell(["coverage", "erase"])
Peter Goldsborough53876c42018-03-09 13:02:02 -08001005
Nikita Shulga01cfea92021-09-14 09:38:34 -07001006 # NS: Disable target determination until it can be made more reliable
1007 # if options.determine_from is not None and os.path.exists(options.determine_from):
1008 # slow_tests = get_slow_tests_based_on_S3(
1009 # TESTS, TARGET_DET_LIST, SLOW_TEST_THRESHOLD
1010 # )
1011 # print_to_stderr(
1012 # "Added the following tests to target_det tests as calculated based on S3:"
1013 # )
1014 # print_to_stderr(slow_tests)
1015 # with open(options.determine_from, "r") as fh:
1016 # touched_files = [
1017 # os.path.normpath(name.strip())
1018 # for name in fh.read().split("\n")
1019 # if len(name.strip()) > 0
1020 # ]
1021 # # HACK: Ensure the 'test' paths can be traversed by Modulefinder
1022 # sys.path.append(test_directory)
1023 # selected_tests = [
1024 # test
1025 # for test in selected_tests
1026 # if should_run_test(
1027 # TARGET_DET_LIST + slow_tests, test, touched_files, options
1028 # )
1029 # ]
1030 # sys.path.remove(test_directory)
Yunus Rahbar7cee7872020-03-03 17:29:14 -08001031
Rong Rong (AI Infra)57d8bcc2021-06-07 17:53:08 -07001032 if IS_IN_CI:
driazati67d8e7b2021-08-25 11:19:49 -07001033 selected_tests = get_reordered_tests(
1034 selected_tests, ENABLE_PR_HISTORY_REORDERING
1035 )
Rong Rong (AI Infra)a5a10fe2021-07-12 11:20:12 -07001036 # downloading test cases configuration to local environment
driazatiab5cf5a2021-08-25 12:58:24 -07001037 get_test_case_configs(dirpath=test_directory)
driazati187a5242021-04-22 10:25:41 -07001038
Eli Uriegasf71cccc2020-07-08 17:24:06 -07001039 has_failed = False
1040 failure_messages = []
Nikita Shulga1bda5e42020-08-26 16:14:17 -07001041 try:
1042 for test in selected_tests:
Pritam Damania06d50b52020-10-22 10:53:07 -07001043 options_clone = copy.deepcopy(options)
1044 if test in USE_PYTEST_LIST:
1045 options_clone.pytest = True
1046 err_message = run_test_module(test, test_directory, options_clone)
Nikita Shulga1bda5e42020-08-26 16:14:17 -07001047 if err_message is None:
1048 continue
Eli Uriegasf71cccc2020-07-08 17:24:06 -07001049 has_failed = True
Nikita Shulga1bda5e42020-08-26 16:14:17 -07001050 failure_messages.append(err_message)
Pritam Damania06d50b52020-10-22 10:53:07 -07001051 if not options_clone.continue_through_error:
Nikita Shulga1bda5e42020-08-26 16:14:17 -07001052 raise RuntimeError(err_message)
1053 print_to_stderr(err_message)
1054 finally:
1055 if options.coverage:
Nikita Shulga6f381de2020-12-18 17:07:05 -08001056 from coverage import Coverage
driazati67d8e7b2021-08-25 11:19:49 -07001057
driazatiab5cf5a2021-08-25 12:58:24 -07001058 with set_cwd(test_directory):
Nikita Shulga6f381de2020-12-18 17:07:05 -08001059 cov = Coverage()
1060 if PYTORCH_COLLECT_COVERAGE:
1061 cov.load()
1062 cov.combine(strict=False)
1063 cov.save()
1064 if not PYTORCH_COLLECT_COVERAGE:
1065 cov.html_report()
Peter Goldsborough53876c42018-03-09 13:02:02 -08001066
Eli Uriegasf71cccc2020-07-08 17:24:06 -07001067 if options.continue_through_error and has_failed:
1068 for err in failure_messages:
Jane Xu85954162020-10-23 14:13:12 -07001069 print_to_stderr(err)
Eli Uriegasf71cccc2020-07-08 17:24:06 -07001070 sys.exit(1)
Peter Goldsborough53876c42018-03-09 13:02:02 -08001071
driazati67d8e7b2021-08-25 11:19:49 -07001072
1073if __name__ == "__main__":
Peter Goldsborough53876c42018-03-09 13:02:02 -08001074 main()