Skip to content

Commit 583aea9

Browse files
committed
Move nanobind test duplication into CMake
Signed-off-by: Aleksandr Motsjonov <soswow@gmail.com>
1 parent a90ecdc commit 583aea9

2 files changed

Lines changed: 60 additions & 99 deletions

File tree

src/cmake/testing.cmake

Lines changed: 53 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ set(OIIO_TESTSUITE_IMAGEDIR "${PROJECT_BINARY_DIR}/testsuite" CACHE PATH
3333
# [ DISABLEVAR variable_name ... ]
3434
# [ SUFFIX suffix ]
3535
# [ ENVIRONMENT "VAR=value" ... ]
36+
# [ ENVIRONMENT_MODIFICATION "VAR=op:value" ... ]
3637
# )
3738
#
3839
# The optional argument IMAGEDIR is used to check whether external test images
@@ -55,8 +56,12 @@ set(OIIO_TESTSUITE_IMAGEDIR "${PROJECT_BINARY_DIR}/testsuite" CACHE PATH
5556
# The optional ENVIRONMENT is a list of environment variables to set for the
5657
# test.
5758
#
59+
# The optional ENVIRONMENT_MODIFICATION is a list of environment variable
60+
# modifications in the format accepted by the CTest ENVIRONMENT_MODIFICATION
61+
# property.
62+
#
5863
macro (oiio_add_tests)
59-
cmake_parse_arguments (_ats "" "SUFFIX;TESTNAME" "URL;IMAGEDIR;LABEL;FOUNDVAR;ENABLEVAR;DISABLEVAR;ENVIRONMENT" ${ARGN})
64+
cmake_parse_arguments (_ats "" "SUFFIX;TESTNAME" "URL;IMAGEDIR;LABEL;FOUNDVAR;ENABLEVAR;DISABLEVAR;ENVIRONMENT;ENVIRONMENT_MODIFICATION" ${ARGN})
6065
# Arguments: <prefix> <options> <one_value_keywords> <multi_value_keywords> args...
6166
set (_ats_testdir "${OIIO_TESTSUITE_IMAGEDIR}/${_ats_IMAGEDIR}")
6267
# If there was a FOUNDVAR param specified and that variable name is
@@ -131,6 +136,11 @@ macro (oiio_add_tests)
131136
"OIIO_TESTSUITE_CUR=${_testdir}"
132137
"Python_EXECUTABLE=${Python3_EXECUTABLE}"
133138
${_ats_ENVIRONMENT})
139+
if (_ats_ENVIRONMENT_MODIFICATION)
140+
set_property(TEST ${_testname} APPEND PROPERTY
141+
ENVIRONMENT_MODIFICATION
142+
${_ats_ENVIRONMENT_MODIFICATION})
143+
endif ()
134144
if (NOT ${_ats_testdir} STREQUAL "")
135145
set_property(TEST ${_testname} APPEND PROPERTY ENVIRONMENT
136146
"OIIO_TESTSUITE_IMAGEDIR=${_ats_testdir}")
@@ -228,25 +238,48 @@ macro (oiio_add_all_tests)
228238
# Python interpreter itself won't be linked with the right asan
229239
# libraries to run correctly.
230240
if (USE_PYTHON AND NOT BUILD_OIIOUTIL_ONLY AND NOT SANITIZE)
231-
oiio_add_tests (
232-
docs-examples-python
233-
python-colorconfig
234-
python-deep
235-
python-imagebuf
236-
python-imagecache
237-
python-imageoutput
238-
python-imagespec
239-
python-paramlist
240-
python-roi
241-
python-texturesys
242-
python-typedesc
243-
filters
244-
)
245-
# These Python tests also need access to oiio-images
246-
oiio_add_tests (
247-
python-imageinput python-imagebufalgo
248-
IMAGEDIR oiio-images
249-
)
241+
set (pybind11_python_path_mod
242+
"PYTHONPATH=path_list_prepend:${CMAKE_BINARY_DIR}/lib/python/site-packages")
243+
set (nanobind_python_tests
244+
python-imagespec
245+
python-paramlist
246+
python-roi
247+
python-typedesc)
248+
set (nanobind_python_test_suffix ".nanobind")
249+
if (OIIO_BUILD_PYTHON_PYBIND11)
250+
oiio_add_tests (
251+
docs-examples-python
252+
python-colorconfig
253+
python-deep
254+
python-imagebuf
255+
python-imagecache
256+
python-imageoutput
257+
python-imagespec
258+
python-paramlist
259+
python-roi
260+
python-texturesys
261+
python-typedesc
262+
filters
263+
ENVIRONMENT_MODIFICATION ${pybind11_python_path_mod}
264+
)
265+
# These Python tests also need access to oiio-images
266+
oiio_add_tests (
267+
python-imageinput python-imagebufalgo
268+
IMAGEDIR oiio-images
269+
ENVIRONMENT_MODIFICATION ${pybind11_python_path_mod}
270+
)
271+
else ()
272+
set (nanobind_python_test_suffix "")
273+
endif ()
274+
275+
if (OIIO_BUILD_PYTHON_NANOBIND)
276+
oiio_add_tests (
277+
${nanobind_python_tests}
278+
SUFFIX ${nanobind_python_test_suffix}
279+
ENVIRONMENT_MODIFICATION
280+
"PYTHONPATH=path_list_prepend:${CMAKE_BINARY_DIR}/lib/python/nanobind"
281+
)
282+
endif ()
250283
endif ()
251284

252285
oiio_add_tests (oiiotool-color

testsuite/runtest.py

Lines changed: 7 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@
1212
import difflib
1313
import filecmp
1414
import shutil
15-
import shlex
16-
from typing import Optional
1715

1816
from optparse import OptionParser
1917

@@ -55,12 +53,6 @@ def make_relpath (path: str, start: str=os.curdir) -> str:
5553
p = os.path.relpath (path, start)
5654
return p if platform.system() != 'Windows' else p.replace ('\\', '/')
5755

58-
59-
def shell_quote(arg: str) -> str:
60-
if platform.system() == 'Windows':
61-
return subprocess.list2cmdline([arg])
62-
return shlex.quote(arg)
63-
6456
# Try to figure out where some key things are. Go by env variables set by
6557
# the cmake tests, but if those aren't set, assume somebody is running
6658
# this script by hand from inside build/testsuite/TEST and that
@@ -85,20 +77,11 @@ def shell_quote(arg: str) -> str:
8577
refdir = "ref/"
8678
refdirlist = [ refdir ]
8779
mytest = os.path.split(os.path.abspath(os.getcwd()))[-1]
88-
if str(mytest).endswith('.batch') :
89-
mytest = mytest.split('.')[0]
80+
if str(mytest).endswith('.batch') or str(mytest).endswith('.nanobind') :
81+
mytest = mytest.rsplit('.', 1)[0]
9082
test_source_dir = os.getenv('OIIO_TESTSUITE_SRC',
9183
os.path.join(OIIO_TESTSUITE_ROOT, mytest))
9284

93-
# Python tests listed here also run against the staged nanobind package when
94-
# it exists in the current build tree.
95-
nanobind_python_tests = {
96-
"python-imagespec",
97-
"python-paramlist",
98-
"python-roi",
99-
"python-typedesc",
100-
}
101-
10285
def oiio_app (app: str) -> str:
10386
if (platform.system () != 'Windows' or options.devenv_config == ""):
10487
cmd = os.path.join(OIIO_BUILD_ROOT, "bin", app) + " "
@@ -118,7 +101,6 @@ def oiio_app (app: str) -> str:
118101

119102
command = ""
120103
outputs = [ "out.txt" ] # default
121-
ref_name_overrides = {}
122104

123105
# The image comparison thresholds are tricky to remember. Here's the key:
124106
# A test fails if more than `failpercent` of pixel values differ by more
@@ -372,18 +354,16 @@ def oiiotool (args: str, silent: bool=False, concat: bool=True, failureok: bool=
372354
# the identical name, and if that fails, it will look for alternatives of
373355
# the form "basename-*.ext" (or ANY match in the ref directory, if anymatch
374356
# is True).
375-
def checkref (name: str, refdirlist: list[str], refname: Optional[str]=None) -> tuple[bool, str]:
357+
def checkref (name: str, refdirlist: list[str]) -> tuple[bool, str]:
376358
# Break the output into prefix+extension
377-
if refname is None:
378-
refname = name
379-
(prefix, extension) = os.path.splitext(refname)
359+
(prefix, extension) = os.path.splitext(name)
380360
ok = 0
381361
for ref in refdirlist :
382362
# We will first compare name to ref/name, and if that fails, we will
383363
# compare it to everything else that matches ref/prefix-*.extension.
384364
# That allows us to have multiple matching variants for different
385365
# platforms, etc.
386-
defaulttest = os.path.join(ref,refname)
366+
defaulttest = os.path.join(ref,name)
387367
if anymatch :
388368
pattern = "*.*"
389369
else :
@@ -420,9 +400,6 @@ def runtest (command: str, outputs: list[str], failureok: int=0) -> int :
420400
err = 0
421401
# print ("working dir = " + tmpdir)
422402
os.chdir (srcdir)
423-
for out in ("out.txt", "out.err.txt", "out-nanobind.txt"):
424-
if os.path.exists(out):
425-
os.remove(out)
426403
open ("out.txt", "w").close() # truncate out.txt
427404
open ("out.err.txt", "w").close() # truncate out.txt
428405
if os.path.isfile("debug.log") :
@@ -460,8 +437,7 @@ def runtest (command: str, outputs: list[str], failureok: int=0) -> int :
460437
if os.path.exists('crlf.txt') :
461438
os.remove('crlf.txt')
462439

463-
refname = ref_name_overrides.get(out, out)
464-
(ok, testfile) = checkref (out, refdirlist, refname=refname)
440+
(ok, testfile) = checkref (out, refdirlist)
465441

466442
if ok :
467443
if extension in image_extensions :
@@ -501,61 +477,13 @@ def runtest (command: str, outputs: list[str], failureok: int=0) -> int :
501477

502478

503479
#
504-
# Read the individual run.py file for this test, which will define
480+
# Read the individual run.py file for this test, which will define
505481
# command and outputs.
506482
#
507483
with open(os.path.join(test_source_dir,"run.py")) as f:
508484
code = compile(f.read(), "run.py", 'exec')
509485
exec (code)
510486

511-
# For tests that have a nanobind port, run the same canonical Python test
512-
# body a second time against the staged nanobind package from the current
513-
# build tree. Keep the output separate so failures still indicate which
514-
# backend mismatched the shared reference output.
515-
nanobind_package = os.path.join(
516-
OIIO_BUILD_ROOT, "lib", "python", "nanobind", "OpenImageIO", "__init__.py"
517-
)
518-
if mytest in nanobind_python_tests and os.path.exists(nanobind_package):
519-
nanobind_test_scripts = sorted(glob.glob(os.path.join(test_source_dir, "src", "*.py")))
520-
if len(nanobind_test_scripts) != 1:
521-
raise RuntimeError(
522-
"Expected exactly one Python test script under "
523-
+ os.path.join(test_source_dir, "src")
524-
+ ", found "
525-
+ str(len(nanobind_test_scripts))
526-
)
527-
nanobind_test_script = make_relpath(nanobind_test_scripts[0], tmpdir)
528-
nanobind_package_root = make_relpath(
529-
os.path.join(OIIO_BUILD_ROOT, "lib", "python", "nanobind"),
530-
tmpdir,
531-
)
532-
# Re-run the same canonical test script as a standalone program, but
533-
# with the staged nanobind package inserted first on sys.path so
534-
# `import OpenImageIO` resolves to the nanobind backend.
535-
nanobind_code = (
536-
"import runpy, sys\n"
537-
+ "sys.path.insert(0, "
538-
+ repr(nanobind_package_root)
539-
+ ")\n"
540-
+ "runpy.run_path("
541-
+ repr(nanobind_test_script)
542-
+ ", run_name='__main__')\n"
543-
)
544-
command += (
545-
" ; "
546-
+ shell_quote(pythonbin)
547-
+ " -c "
548-
+ shell_quote(nanobind_code)
549-
+ " > out-nanobind.txt"
550-
)
551-
# Example of final command for `python-roi` would be:
552-
# python src/test_roi.py > out.txt ; \
553-
# python -c 'import runpy, sys
554-
# sys.path.insert(0, "../../lib/python/nanobind")
555-
# runpy.run_path("src/test_roi.py", run_name="__main__")' > out-nanobind.txt
556-
outputs.append("out-nanobind.txt")
557-
ref_name_overrides["out-nanobind.txt"] = "out.txt"
558-
559487
# Allow a little more slop for slight pixel differences when in DEBUG
560488
# mode or when running on remote CI machines.
561489
if (os.getenv('CI') or os.getenv('DEBUG')) :

0 commit comments

Comments
 (0)