Skip to content

Commit 90c9cc2

Browse files
authored
[clang][python][test] Move python binding tests to lit framework (#145855)
As discussed in PR #142353, the current testsuite of the `clang` Python bindings has several issues: - If `libclang.so` cannot be loaded into `python` to run the testsuite, the whole `ninja check-all` aborts. - The result of running the testsuite isn't report like the `lit`-based tests, rendering them almost invisible. - The testsuite is disabled in a non-obvious way (`RUN_PYTHON_TESTS`) in `tests/CMakeLists.txt`, which again doesn't show up in the test results. All these issues can be avoided by integrating the Python bindings tests with `lit`, which is what this patch does: - The actual test lives in `clang/test/bindings/python/bindings.sh` and is run by `lit`. - The current `clang/bindings/python/tests` directory (minus the now-superfluous `CMakeLists.txt`) is moved into the same directory. - The check if `libclang` is loadable (originally from PR #142353) is now handled via a new `lit` feature, `libclang-loadable`. - The various ways to disable the tests have been turned into `XFAIL`s as appropriate. - AArch64 doesn't `FAIL` any longer, so no `XFAIL` is necessary. - It keeps the `check-clang-python` target for use by the Clang Python CI. Tested on `sparc-sun-solaris2.11`, `sparcv9-sun-solaris2.11`, `i386-pc-solaris2.11`, `amd64-pc-solaris2.11`, `i686-pc-linux-gnu`, and `x86_64-pc-linux-gnu`.
1 parent 58b7d20 commit 90c9cc2

40 files changed

+87
-69
lines changed

.github/workflows/libclang-python-tests.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,15 @@ on:
1010
- 'main'
1111
paths:
1212
- 'clang/bindings/python/**'
13+
- 'clang/test/bindings/python/**'
1314
- 'clang/tools/libclang/**'
14-
- 'clang/CMakeList.txt'
1515
- '.github/workflows/libclang-python-tests.yml'
1616
- '.github/workflows/llvm-project-tests.yml'
1717
pull_request:
1818
paths:
1919
- 'clang/bindings/python/**'
20+
- 'clang/test/bindings/python/**'
2021
- 'clang/tools/libclang/**'
21-
- 'clang/CMakeList.txt'
2222
- '.github/workflows/libclang-python-tests.yml'
2323
- '.github/workflows/llvm-project-tests.yml'
2424

clang/CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -530,7 +530,6 @@ if( CLANG_INCLUDE_TESTS )
530530
clang_unit_site_config=${CMAKE_CURRENT_BINARY_DIR}/test/Unit/lit.site.cfg
531531
)
532532
add_subdirectory(test)
533-
add_subdirectory(bindings/python/tests)
534533

535534
if(CLANG_BUILT_STANDALONE)
536535
umbrella_lit_testsuite_end(check-all)

clang/bindings/python/tests/CMakeLists.txt

Lines changed: 0 additions & 66 deletions
This file was deleted.

clang/test/CMakeLists.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,17 @@ add_custom_target(clang-test)
205205
add_dependencies(clang-test check-clang)
206206
set_target_properties(clang-test PROPERTIES FOLDER "Clang/Tests")
207207

208+
# Allow running Clang Python binding tests separately from CI.
209+
add_lit_testsuite(check-clang-python "Running the Clang Python tests"
210+
${CMAKE_CURRENT_BINARY_DIR}
211+
#LIT ${LLVM_LIT}
212+
PARAMS ${CLANG_TEST_PARAMS}
213+
DEPENDS ${CLANG_TEST_DEPS}
214+
ARGS ${CLANG_TEST_EXTRA_ARGS} --filter=bindings.sh
215+
# Avoid running tests twice.
216+
EXCLUDE_FROM_CHECK_ALL
217+
)
218+
208219
# FIXME: This logic can be removed once all buildbots have moved
209220
# debuginfo-test from clang/test to llvm/projects or monorepo.
210221
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/debuginfo-tests)
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#!/bin/sh
2+
3+
# UNSUPPORTED: !libclang-loadable
4+
5+
# Tests fail on Windows, and need someone knowledgeable to fix.
6+
# It's not clear whether it's a test or a valid binding problem.
7+
# XFAIL: target={{.*windows.*}}
8+
9+
# The Python FFI interface is broken on AIX: https://bugs.python.org/issue38628.
10+
# XFAIL: target={{.*-aix.*}}
11+
12+
# Hexagon has known test failures that need to be addressed.
13+
# SystemZ has broken Python/FFI interface:
14+
# https://reviews.llvm.org/D52840#1265716
15+
# XFAIL: target={{(hexagon|s390x)-.*}}
16+
# python SEGVs on Linux/sparc64 when loading libclang.so. Seems to be an FFI
17+
# issue, too.
18+
# XFAIL: target={{sparc.*-.*-linux.*}}
19+
20+
# Tests will fail if cross-compiling for a different target, as tests will try
21+
# to use the host Python3_EXECUTABLE and make FFI calls to functions in target
22+
# libraries.
23+
#
24+
# FIXME: Consider a solution that allows better control over these tests in
25+
# a crosscompiling scenario. e.g. registering them with lit to allow them to
26+
# be explicitly skipped via appropriate LIT_ARGS, or adding a mechanism to
27+
# allow specifying a python interpreter compiled for the target that could
28+
# be executed using qemu-user.
29+
# XFAIL: !native
30+
31+
# RUN: env PYTHONPATH=%S/../../../bindings/python \
32+
# RUN: CLANG_LIBRARY_PATH=%libdir \
33+
# RUN: %python -m unittest discover -s %S/tests
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
def is_libclang_loadable():
2+
# Do not try to run if libclang was built with sanitizers because
3+
# the sanitizer library will likely be loaded too late to perform
4+
# interception and will then fail.
5+
# We could use LD_PRELOAD/DYLD_INSERT_LIBRARIES but this isn't
6+
# portable so its easier just to not run the tests when building
7+
# with ASan.
8+
if config.llvm_use_sanitizer != "":
9+
return False
10+
try:
11+
sys.path.append(os.path.join(config.clang_src_dir, "bindings/python"))
12+
from clang.cindex import Config
13+
conf = Config()
14+
Config.set_library_path(config.clang_lib_dir)
15+
conf.lib
16+
return True
17+
except Exception as e:
18+
# Expected failure modes are considered benign when nothing can be
19+
# done about them.
20+
#
21+
# Cannot load a 32-bit libclang.so into a 64-bit python.
22+
if "wrong ELF class: ELFCLASS32" in str(e):
23+
return False
24+
# If libclang.so is missing, it must have been disabled intentionally,
25+
# e.g. by building with LLVM_ENABLE_PIC=OFF.
26+
elif "No such file or directory" in str(e):
27+
return False
28+
# Unexpected failure modes need to be investigated to either fix an
29+
# underlying bug or accept the failure, so return True. This causes
30+
# tests to run and FAIL, drawing developer attention.
31+
else:
32+
print("warning: unhandled failure in is_libclang_loadable: "
33+
+ str(e), file=sys.stderr)
34+
return True
35+
36+
if is_libclang_loadable():
37+
config.available_features.add("libclang-loadable")
38+
39+
config.substitutions.append(('%libdir', config.clang_lib_dir))
40+
41+
config.suffixes = ['.sh']

0 commit comments

Comments
 (0)