Skip to content

Commit 35834a4

Browse files
huydhnpytorchmergebot
authored andcommitted
Run C++ tests on CI with run_test.py (pytorch#99956)
After pytorch#99559, we can now run C++ test with `run_test.py`. Although advance features such as `--import-slow-tests` and `--import-disabled-tests` won't work for now, there will still be a gain in reliability and performance as C++ can now be retried and run in parallel. This covers all C++ tests in the CI including aten, libtorch, and Vulkan C++ tests across all platforms Linux, Windows, MacOS. Notes: * To support C++ test discovery, the env variable `CPP_TESTS_DIR` can be set to where the C++ test binaries is located * Support pytest -k argument via run_test as this is used by pytest-cpp to replace `--gtest-filter` * The XML output is in pytest format, but it's ok now because we don't have slow test or flaky test support for C++ test yet * ~~I need to figure out why conftest.py doesn't work when I invoke pytest directly for C++ test, so `--sc` is not available for C++ tests at the moment. Proper pytest plugin like stepwise works fine though. I'll investigate and fix it in a separate PR~~ Found the cause, `conftest.py` is per directory and needs to be in any arbitrary directory that holds C++ test * Two tests `test_api` and `test_tensorexpr` timed out on ASAN, I suspect that ASAN is now used on top of the python executable, which is slower than running native C++ code. IMO, it's ok to run these tests as before on ASAN for now Pull Request resolved: pytorch#99956 Approved by: https://github.com/clee2000, https://github.com/ZainRizvi
1 parent a8c2cd1 commit 35834a4

File tree

5 files changed

+171
-120
lines changed

5 files changed

+171
-120
lines changed

.ci/pytorch/macos-test.sh

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,13 +71,14 @@ test_libtorch() {
7171
VERBOSE=1 DEBUG=1 python "$BUILD_LIBTORCH_PY"
7272
popd
7373

74-
python tools/download_mnist.py --quiet -d test/cpp/api/mnist
74+
MNIST_DIR="${PWD}/test/cpp/api/mnist"
75+
python tools/download_mnist.py --quiet -d "${MNIST_DIR}"
7576

7677
# Unfortunately it seems like the test can't load from miniconda3
7778
# without these paths being set
7879
export DYLD_LIBRARY_PATH="$DYLD_LIBRARY_PATH:$PWD/miniconda3/lib"
7980
export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$PWD/miniconda3/lib"
80-
TORCH_CPP_TEST_MNIST_PATH="test/cpp/api/mnist" "$CPP_BUILD"/caffe2/bin/test_api
81+
TORCH_CPP_TEST_MNIST_PATH="${MNIST_DIR}" CPP_TESTS_DIR="${CPP_BUILD}/caffe2/bin" python test/run_test.py --cpp --verbose -i cpp/test_api
8182

8283
assert_git_not_dirty
8384
fi

.ci/pytorch/test.sh

Lines changed: 59 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ test_inductor() {
271271
# docker build uses bdist_wheel which does not work with test_aot_inductor
272272
# TODO: need a faster way to build
273273
BUILD_AOT_INDUCTOR_TEST=1 python setup.py develop
274-
LD_LIBRARY_PATH="$TORCH_LIB_DIR $TORCH_BIN_DIR"/test_aot_inductor
274+
CPP_TESTS_DIR="${BUILD_BIN_DIR}" LD_LIBRARY_PATH="${TORCH_LIB_DIR}" python test/run_test.py --cpp --verbose -i cpp/test_aot_inductor
275275
}
276276

277277
# "Global" flags for inductor benchmarking controlled by TEST_CONFIG
@@ -547,43 +547,60 @@ test_libtorch() {
547547
ln -sf "$TORCH_LIB_DIR"/libtbb* "$TORCH_BIN_DIR"
548548
ln -sf "$TORCH_LIB_DIR"/libnvfuser* "$TORCH_BIN_DIR"
549549

550+
export CPP_TESTS_DIR="${TORCH_BIN_DIR}"
551+
550552
# Start background download
551-
python tools/download_mnist.py --quiet -d test/cpp/api/mnist &
553+
MNIST_DIR="${PWD}/test/cpp/api/mnist"
554+
python tools/download_mnist.py --quiet -d "${MNIST_DIR}" &
552555

553-
# Make test_reports directory
554-
# NB: the ending test_libtorch must match the current function name for the current
555-
# test reporting process to function as expected.
556-
TEST_REPORTS_DIR=test/test-reports/cpp-unittest/test_libtorch
557-
mkdir -p $TEST_REPORTS_DIR
556+
# Prepare the model used by test_jit, the model needs to be in the test directory
557+
# to get picked up by run_test
558+
pushd test
559+
python cpp/jit/tests_setup.py setup
560+
popd
558561

559562
# Run JIT cpp tests
560-
python test/cpp/jit/tests_setup.py setup
561-
562563
if [[ "$BUILD_ENVIRONMENT" == *cuda* ]]; then
563-
"$TORCH_BIN_DIR"/test_jit --gtest_output=xml:$TEST_REPORTS_DIR/test_jit.xml
564-
"$TORCH_BIN_DIR"/nvfuser_tests --gtest_output=xml:$TEST_REPORTS_DIR/nvfuser_tests.xml
564+
python test/run_test.py --cpp --verbose -i cpp/test_jit cpp/nvfuser_tests
565565
else
566-
"$TORCH_BIN_DIR"/test_jit --gtest_filter='-*CUDA' --gtest_output=xml:$TEST_REPORTS_DIR/test_jit.xml
566+
# CUDA tests have already been skipped when CUDA is not available
567+
python test/run_test.py --cpp --verbose -i cpp/test_jit -k "not CUDA"
567568
fi
568569

569570
# Run Lazy Tensor cpp tests
570571
if [[ "$BUILD_ENVIRONMENT" == *cuda* && "$TEST_CONFIG" != *nogpu* ]]; then
571-
LTC_TS_CUDA=1 "$TORCH_BIN_DIR"/test_lazy --gtest_output=xml:$TEST_REPORTS_DIR/test_lazy.xml
572+
LTC_TS_CUDA=1 python test/run_test.py --cpp --verbose -i cpp/test_lazy
572573
else
573-
"$TORCH_BIN_DIR"/test_lazy --gtest_output=xml:$TEST_REPORTS_DIR/test_lazy.xml
574+
python test/run_test.py --cpp --verbose -i cpp/test_lazy
574575
fi
575576

576-
python test/cpp/jit/tests_setup.py shutdown
577+
# Cleaning up test artifacts in the test folder
578+
pushd test
579+
python cpp/jit/tests_setup.py shutdown
580+
popd
577581

578582
# Wait for background download to finish
579583
wait
580-
# Exclude IMethodTest that relies on torch::deploy, which will instead be ran in test_deploy.
581-
OMP_NUM_THREADS=2 TORCH_CPP_TEST_MNIST_PATH="test/cpp/api/mnist" "$TORCH_BIN_DIR"/test_api --gtest_filter='-IMethodTest.*' --gtest_output=xml:$TEST_REPORTS_DIR/test_api.xml
582-
"$TORCH_BIN_DIR"/test_tensorexpr --gtest_output=xml:$TEST_REPORTS_DIR/test_tensorexpr.xml
584+
585+
if [[ "$BUILD_ENVIRONMENT" == *asan* ]]; then
586+
TEST_REPORTS_DIR=test/test-reports/cpp-unittest/test_libtorch
587+
mkdir -p $TEST_REPORTS_DIR
588+
589+
# TODO: Not quite sure why these tests time out only on ASAN, probably
590+
# this is due to the fact that a python executable is used and ASAN
591+
# treats that differently
592+
OMP_NUM_THREADS=2 TORCH_CPP_TEST_MNIST_PATH="${MNIST_DIR}" "$TORCH_BIN_DIR"/test_api --gtest_filter='-IMethodTest.*' --gtest_output=xml:$TEST_REPORTS_DIR/test_api.xml
593+
"$TORCH_BIN_DIR"/test_tensorexpr --gtest_output=xml:$TEST_REPORTS_DIR/test_tensorexpr.xml
594+
else
595+
# Exclude IMethodTest that relies on torch::deploy, which will instead be ran in test_deploy
596+
OMP_NUM_THREADS=2 TORCH_CPP_TEST_MNIST_PATH="${MNIST_DIR}" python test/run_test.py --cpp --verbose -i cpp/test_api -k "not IMethodTest"
597+
python test/run_test.py --cpp --verbose -i cpp/test_tensorexpr
598+
fi
583599

584600
if [[ "${BUILD_ENVIRONMENT}" != *android* && "${BUILD_ENVIRONMENT}" != *cuda* && "${BUILD_ENVIRONMENT}" != *asan* ]]; then
585-
# TODO: Consider to run static_runtime_test from $TORCH_BIN_DIR (may need modify build script)
586-
"$BUILD_BIN_DIR"/static_runtime_test --gtest_output=xml:$TEST_REPORTS_DIR/static_runtime_test.xml
601+
# NB: This test is not under TORCH_BIN_DIR but under BUILD_BIN_DIR
602+
export CPP_TESTS_DIR="${BUILD_BIN_DIR}"
603+
python test/run_test.py --cpp --verbose -i cpp/static_runtime_test
587604
fi
588605

589606
assert_git_not_dirty
@@ -595,26 +612,21 @@ test_aot_compilation() {
595612
ln -sf "$TORCH_LIB_DIR"/libc10* "$TORCH_BIN_DIR"
596613
ln -sf "$TORCH_LIB_DIR"/libtorch* "$TORCH_BIN_DIR"
597614

598-
# Make test_reports directory
599-
# NB: the ending test_libtorch must match the current function name for the current
600-
# test reporting process to function as expected.
601-
TEST_REPORTS_DIR=test/test-reports/cpp-unittest/test_aot_compilation
602-
mkdir -p $TEST_REPORTS_DIR
603-
if [ -f "$TORCH_BIN_DIR"/test_mobile_nnc ]; then "$TORCH_BIN_DIR"/test_mobile_nnc --gtest_output=xml:$TEST_REPORTS_DIR/test_mobile_nnc.xml; fi
604-
# shellcheck source=test/mobile/nnc/test_aot_compile.sh
605-
if [ -f "$TORCH_BIN_DIR"/aot_model_compiler_test ]; then source test/mobile/nnc/test_aot_compile.sh; fi
615+
if [ -f "$TORCH_BIN_DIR"/test_mobile_nnc ]; then
616+
CPP_TESTS_DIR="${TORCH_BIN_DIR}" python test/run_test.py --cpp --verbose -i cpp/test_mobile_nnc
617+
fi
618+
619+
if [ -f "$TORCH_BIN_DIR"/aot_model_compiler_test ]; then
620+
source test/mobile/nnc/test_aot_compile.sh
621+
fi
606622
}
607623

608624
test_vulkan() {
609625
if [[ "$BUILD_ENVIRONMENT" == *vulkan* ]]; then
610626
ln -sf "$TORCH_LIB_DIR"/libtorch* "$TORCH_TEST_DIR"
611627
ln -sf "$TORCH_LIB_DIR"/libc10* "$TORCH_TEST_DIR"
612628
export VK_ICD_FILENAMES=/var/lib/jenkins/swiftshader/swiftshader/build/Linux/vk_swiftshader_icd.json
613-
# NB: the ending test_vulkan must match the current function name for the current
614-
# test reporting process to function as expected.
615-
TEST_REPORTS_DIR=test/test-reports/cpp-vulkan/test_vulkan
616-
mkdir -p $TEST_REPORTS_DIR
617-
LD_LIBRARY_PATH=/var/lib/jenkins/swiftshader/swiftshader/build/Linux/ "$TORCH_TEST_DIR"/vulkan_api_test --gtest_output=xml:$TEST_REPORTS_DIR/vulkan_test.xml
629+
CPP_TESTS_DIR="${TORCH_TEST_DIR}" LD_LIBRARY_PATH=/var/lib/jenkins/swiftshader/swiftshader/build/Linux/ python test/run_test.py --cpp --verbose -i cpp/vulkan_api_test
618630
fi
619631
}
620632

@@ -631,22 +643,24 @@ test_distributed() {
631643
echo "Testing distributed C++ tests"
632644
ln -sf "$TORCH_LIB_DIR"/libtorch* "$TORCH_BIN_DIR"
633645
ln -sf "$TORCH_LIB_DIR"/libc10* "$TORCH_BIN_DIR"
634-
# NB: the ending test_distributed must match the current function name for the current
635-
# test reporting process to function as expected.
636-
TEST_REPORTS_DIR=test/test-reports/cpp-distributed/test_distributed
637-
mkdir -p $TEST_REPORTS_DIR
638-
"$TORCH_BIN_DIR"/FileStoreTest --gtest_output=xml:$TEST_REPORTS_DIR/FileStoreTest.xml
639-
"$TORCH_BIN_DIR"/HashStoreTest --gtest_output=xml:$TEST_REPORTS_DIR/HashStoreTest.xml
640-
"$TORCH_BIN_DIR"/TCPStoreTest --gtest_output=xml:$TEST_REPORTS_DIR/TCPStoreTest.xml
646+
647+
export CPP_TESTS_DIR="${TORCH_BIN_DIR}"
648+
# These are distributed tests, so let's continue running them sequentially here to avoid
649+
# any surprise
650+
python test/run_test.py --cpp --verbose -i cpp/FileStoreTest
651+
python test/run_test.py --cpp --verbose -i cpp/HashStoreTest
652+
python test/run_test.py --cpp --verbose -i cpp/TCPStoreTest
641653

642654
MPIEXEC=$(command -v mpiexec)
643655
if [[ -n "$MPIEXEC" ]]; then
656+
# NB: mpiexec only works directly with the C++ test binary here
644657
MPICMD="${MPIEXEC} -np 2 $TORCH_BIN_DIR/ProcessGroupMPITest"
645658
eval "$MPICMD"
646659
fi
647-
"$TORCH_BIN_DIR"/ProcessGroupGlooTest --gtest_output=xml:$TEST_REPORTS_DIR/ProcessGroupGlooTest.xml
648-
"$TORCH_BIN_DIR"/ProcessGroupNCCLTest --gtest_output=xml:$TEST_REPORTS_DIR/ProcessGroupNCCLTest.xml
649-
"$TORCH_BIN_DIR"/ProcessGroupNCCLErrorsTest --gtest_output=xml:$TEST_REPORTS_DIR/ProcessGroupNCCLErrorsTest.xml
660+
661+
python test/run_test.py --cpp --verbose -i cpp/ProcessGroupGlooTest
662+
python test/run_test.py --cpp --verbose -i cpp/ProcessGroupNCCLTest
663+
python test/run_test.py --cpp --verbose -i cpp/ProcessGroupNCCLErrorsTest
650664
fi
651665
}
652666

@@ -658,9 +672,8 @@ test_rpc() {
658672
ln -sf "$TORCH_LIB_DIR"/libtorch* "$TORCH_BIN_DIR"
659673
ln -sf "$TORCH_LIB_DIR"/libc10* "$TORCH_BIN_DIR"
660674
ln -sf "$TORCH_LIB_DIR"/libtbb* "$TORCH_BIN_DIR"
661-
TEST_REPORTS_DIR=test/test-reports/cpp-rpc/test_rpc
662-
mkdir -p $TEST_REPORTS_DIR
663-
"$TORCH_BIN_DIR"/test_cpp_rpc --gtest_output=xml:$TEST_REPORTS_DIR/test_cpp_rpc.xml
675+
676+
CPP_TESTS_DIR="${TORCH_BIN_DIR}" python test/run_test.py --cpp --verbose -i cpp/test_cpp_rpc
664677
fi
665678
}
666679

.ci/pytorch/win-test-helpers/test_libtorch.bat

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,16 @@ if "%USE_CUDA%" == "0" IF NOT "%CUDA_VERSION%" == "cpu" exit /b 0
55
call %SCRIPT_HELPERS_DIR%\setup_pytorch_env.bat
66
if errorlevel 1 exit /b 1
77

8-
cd %TMP_DIR_WIN%\build\torch\bin
9-
set TEST_OUT_DIR=%~dp0\..\..\..\test\test-reports\cpp-unittest
10-
md %TEST_OUT_DIR%
8+
:: Save the current working directory so that we can go back there
9+
set CWD=%cd%
10+
11+
set CPP_TESTS_DIR=%TMP_DIR_WIN%\build\torch\bin
1112
set PATH=C:\Program Files\NVIDIA Corporation\NvToolsExt\bin\x64;%TMP_DIR_WIN%\build\torch\lib;%PATH%
1213

13-
set TEST_API_OUT_DIR=%TEST_OUT_DIR%\test_api
14-
md %TEST_API_OUT_DIR%
15-
test_api.exe --gtest_filter="-IntegrationTest.MNIST*" --gtest_output=xml:%TEST_API_OUT_DIR%\test_api.xml
14+
set TORCH_CPP_TEST_MNIST_PATH=%CWD%\test\cpp\api\mnist
15+
python tools\download_mnist.py --quiet -d %TORCH_CPP_TEST_MNIST_PATH%
16+
17+
python test\run_test.py --cpp --verbose -i cpp/test_api
1618
if errorlevel 1 exit /b 1
1719
if not errorlevel 0 exit /b 1
1820

@@ -25,6 +27,10 @@ for /r "." %%a in (*.exe) do (
2527
goto :eof
2628

2729
:libtorch_check
30+
31+
cd %CWD%
32+
set CPP_TESTS_DIR=%TMP_DIR_WIN%\build\torch\test
33+
2834
:: Skip verify_api_visibility as it a compile level test
2935
if "%~1" == "verify_api_visibility" goto :eof
3036

@@ -42,12 +48,12 @@ if "%~1" == "utility_ops_gpu_test" goto :eof
4248

4349
echo Running "%~2"
4450
if "%~1" == "c10_intrusive_ptr_benchmark" (
51+
:: NB: This is not a gtest executable file, thus couldn't be handled by pytest-cpp
4552
call "%~2"
4653
goto :eof
4754
)
48-
:: Differentiating the test report directories is crucial for test time reporting.
49-
md %TEST_OUT_DIR%\%~n2
50-
call "%~2" --gtest_output=xml:%TEST_OUT_DIR%\%~n2\%~1.xml
55+
56+
python test\run_test.py --cpp --verbose -i "cpp/%~1"
5157
if errorlevel 1 (
5258
echo %1 failed with exit code %errorlevel%
5359
exit /b 1

aten/tools/run_tests.sh

Lines changed: 41 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3,75 +3,78 @@ set -x
33
set -e
44

55
VALGRIND_SUP="${PWD}/`dirname $0`/valgrind.sup"
6-
pushd $1
6+
export CPP_TESTS_DIR=$1
77

88
VALGRIND=${VALGRIND:=ON}
9-
./basic
10-
./atest
11-
./scalar_test
12-
./broadcast_test
13-
./wrapdim_test
14-
./apply_utils_test
15-
./dlconvertor_test
16-
./native_test
17-
./scalar_tensor_test
9+
python test/run_test.py --cpp --verbose -i \
10+
cpp/basic \
11+
cpp/atest \
12+
cpp/scalar_test \
13+
cpp/broadcast_test \
14+
cpp/wrapdim_test \
15+
cpp/apply_utils_test \
16+
cpp/dlconvertor_test \
17+
cpp/native_test \
18+
cpp/scalar_tensor_test \
19+
cpp/undefined_tensor_test \
20+
cpp/extension_backend_test \
21+
cpp/lazy_tensor_test \
22+
cpp/tensor_iterator_test \
23+
cpp/Dimname_test \
24+
cpp/Dict_test \
25+
cpp/NamedTensor_test \
26+
cpp/cpu_generator_test \
27+
cpp/legacy_vmap_test \
28+
cpp/operators_test
29+
1830
if [[ -x ./tensor_interop_test ]]; then
19-
./tensor_interop_test
31+
python test/run_test.py --cpp --verbose -i cpp/tensor_interop_test
2032
fi
21-
./undefined_tensor_test
22-
./extension_backend_test
23-
./lazy_tensor_test
24-
./tensor_iterator_test
25-
./Dimname_test
26-
./Dict_test
27-
./NamedTensor_test
28-
./cpu_generator_test
29-
./legacy_vmap_test
30-
./operators_test
3133
if [[ -x ./cudnn_test ]]; then
32-
./cudnn_test
34+
python test/run_test.py --cpp --verbose -i cpp/cudnn_test
3335
fi
3436
if [[ -x ./cuda_generator_test ]]; then
35-
./cuda_generator_test
37+
python test/run_test.py --cpp --verbose -i cpp/cuda_generator_test
3638
fi
3739
if [[ -x ./apply_test ]]; then
38-
./apply_test
40+
python test/run_test.py --cpp --verbose -i cpp/apply_test
3941
fi
4042
if [[ -x ./stream_test ]]; then
41-
./stream_test
43+
python test/run_test.py --cpp --verbose -i cpp/stream_test
4244
fi
4345
if [[ -x ./cuda_half_test ]]; then
44-
./cuda_half_test
46+
python test/run_test.py --cpp --verbose -i cpp/cuda_half_test
4547
fi
4648
if [[ -x ./cuda_vectorized_test ]]; then
47-
./cuda_vectorized_test
49+
python test/run_test.py --cpp --verbose -i cpp/cuda_vectorized_test
4850
fi
4951
if [[ -x ./cuda_distributions_test ]]; then
50-
./cuda_distributions_test
52+
python test/run_test.py --cpp --verbose -i cpp/cuda_distributions_test
5153
fi
5254
if [[ -x ./cuda_optional_test ]]; then
53-
./cuda_optional_test
55+
python test/run_test.py --cpp --verbose -i cpp/cuda_optional_test
5456
fi
5557
if [[ -x ./cuda_tensor_interop_test ]]; then
56-
./cuda_tensor_interop_test
58+
python test/run_test.py --cpp --verbose -i cpp/cuda_tensor_interop_test
5759
fi
5860
if [[ -x ./cuda_complex_test ]]; then
59-
./cuda_complex_test
61+
python test/run_test.py --cpp --verbose -i cpp/cuda_complex_test
6062
fi
6163
if [[ -x ./cuda_complex_math_test ]]; then
62-
./cuda_complex_math_test
64+
python test/run_test.py --cpp --verbose -i cpp/cuda_complex_math_test
6365
fi
6466
if [[ -x ./cuda_cub_test ]]; then
65-
./cuda_cub_test
67+
python test/run_test.py --cpp --verbose -i cpp/cuda_cub_test
6668
fi
6769
if [[ -x ./cuda_atomic_ops_test ]]; then
68-
./cuda_atomic_ops_test
70+
python test/run_test.py --cpp --verbose -i cpp/cuda_atomic_ops_test
6971
fi
72+
7073
if [ "$VALGRIND" == "ON" ]; then
71-
valgrind --suppressions="$VALGRIND_SUP" --error-exitcode=1 ./basic --gtest_filter='-*CUDA'
74+
# NB: As these tests are invoked by valgrind, let's leave them for now as it's
75+
# unclear if valgrind -> python -> gtest would work
76+
valgrind --suppressions="$VALGRIND_SUP" --error-exitcode=1 "${CPP_TESTS_DIR}/basic" --gtest_filter='-*CUDA'
7277
if [[ -x ./tensor_interop_test ]]; then
73-
valgrind --suppressions="$VALGRIND_SUP" --error-exitcode=1 ./tensor_interop_test
78+
valgrind --suppressions="$VALGRIND_SUP" --error-exitcode=1 "${CPP_TESTS_DIR}/tensor_interop_test"
7479
fi
7580
fi
76-
77-
popd

0 commit comments

Comments
 (0)