Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions tests/test_capi.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,15 @@ class Struct1(xo.Struct):
field2 = xo.Float64


class RawValue(xo.RawUnion):
scalar = xo.Float64
bits = xo.UInt64


class StructRawUnion(xo.Struct):
value = RawValue


class Struct2(xo.Struct):
field1 = xo.Int32
field2 = xo.Float64[:]
Expand Down Expand Up @@ -243,6 +252,36 @@ def test_struct1():
assert p2[0] == s1.field2


def test_raw_union_member_getters():
kernels = StructRawUnion._gen_kernels()
ctx = xo.ContextCpu()
ctx.add_kernels(kernels=kernels)

source = StructRawUnion._gen_c_api().source
assert "StructRawUnion_get_value_scalar" in source
assert "StructRawUnion_get_value_bits" in source
assert "StructRawUnion_get_value(" not in source

value = 3.5
value_bits = np.array([value], dtype=np.float64).view(np.uint64)[0]
s1 = StructRawUnion(value=value)
s2 = StructRawUnion(value=("bits", value_bits))
raw_value = RawValue(value)

assert isinstance(s1.value, RawValue)
assert s1.value.scalar == value
assert s1.value.bits == value_bits
assert s2.value.scalar == value
assert s2.value.bits == value_bits
assert raw_value.scalar == value
assert raw_value.bits == value_bits

assert ctx.kernels.StructRawUnion_get_value_scalar(obj=s1) == value
assert ctx.kernels.StructRawUnion_get_value_bits(obj=s1) == value_bits
assert ctx.kernels.StructRawUnion_get_value_scalar(obj=s2) == value
assert ctx.kernels.StructRawUnion_get_value_bits(obj=s2) == value_bits


def test_struct2():
s2 = Struct2(field1=2, field2=5)

Expand Down
178 changes: 94 additions & 84 deletions tests/test_general.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,146 +12,151 @@
def test_print_mode_default(capsys):
printer = Print()

printer('visible')
printer("visible")

assert capsys.readouterr().out == 'visible\n'
assert capsys.readouterr().out == "visible\n"


def test_print_mode_suppressed(capsys):
printer = Print()
with xo.settings.override(print_mode='suppress'):
printer('hidden')
with xo.settings.override(print_mode="suppress"):
printer("hidden")

assert capsys.readouterr().out == ''
assert capsys.readouterr().out == ""


def test_settings_control_xsuite_printer(capsys):
with xo.settings.override(print_mode='suppress'):
xo._print('hidden')
with xo.settings.override(print_mode="suppress"):
xo._print("hidden")

assert capsys.readouterr().out == ''
assert capsys.readouterr().out == ""


def test_python_setting_overrides_environment_default(capsys):
with xo.settings.override(print_mode='print'):
xo._print('visible')
with xo.settings.override(print_mode="print"):
xo._print("visible")

assert capsys.readouterr().out == 'visible\n'
assert capsys.readouterr().out == "visible\n"


def test_invalid_print_mode_setting():
with pytest.raises(ValueError, match='XSUITE_PRINT_MODE.*print.*suppress'):
xo.settings.print_mode = 'invalid'
with pytest.raises(ValueError, match="XSUITE_PRINT_MODE.*print.*suppress"):
xo.settings.print_mode = "invalid"


def test_settings_override_restores_value_after_error():
original = xo.settings.print_mode

with pytest.raises(RuntimeError):
with xo.settings.override(print_mode='suppress'):
assert xo.settings.print_mode == 'suppress'
with xo.settings.override(print_mode="suppress"):
assert xo.settings.print_mode == "suppress"
raise RuntimeError

assert xo.settings.print_mode == original


def test_settings_are_discoverable():
expected_settings = {
'print_mode',
'progress_indicator',
'allow_kernel_compilation',
'force_kernel_compilation',
'show_kernel_diagnostics',
'cffi_forbid_compile',
'cffi_keep_build_files',
'cuda_backend',
'cuda_fast_compile',
'cuda_compiler',
"print_mode",
"progress_indicator",
"allow_kernel_compilation",
"force_kernel_compilation",
"show_kernel_diagnostics",
"cffi_forbid_compile",
"cffi_keep_build_files",
"cuda_backend",
"cuda_fast_compile",
"cuda_compiler",
}

assert expected_settings <= set(dir(xo.settings))
for name in expected_settings:
assert f'{name}=' in repr(xo.settings)
assert f"{name}=" in repr(xo.settings)
assert name in type(xo.settings).__doc__


def test_print_mode_environment_variable_is_startup_default():
environment = os.environ.copy()
environment['XSUITE_PRINT_MODE'] = 'suppress'
environment["XSUITE_PRINT_MODE"] = "suppress"
code = (
'import xobjects as xo; '
"import xobjects as xo; "
'assert xo.settings.print_mode == "suppress"; '
'xo._print("hidden")')
'xo._print("hidden")'
)

completed = subprocess.run(
[sys.executable, '-c', code],
[sys.executable, "-c", code],
env=environment,
capture_output=True,
text=True,
check=True,
)

assert completed.stdout == ''
assert completed.stdout == ""


def test_print_mode_environment_variable_can_be_overridden_in_python():
environment = os.environ.copy()
environment['XSUITE_PRINT_MODE'] = 'suppress'
environment["XSUITE_PRINT_MODE"] = "suppress"
code = (
'import xobjects as xo; '
"import xobjects as xo; "
'xo.settings.print_mode = "print"; '
'assert xo.settings.print_mode == "print"; '
'xo._print("visible")')
'xo._print("visible")'
)

completed = subprocess.run(
[sys.executable, '-c', code],
[sys.executable, "-c", code],
env=environment,
capture_output=True,
text=True,
check=True,
)

assert completed.stdout == 'visible\n'
assert completed.stdout == "visible\n"


def test_environment_change_after_import_does_not_override_python_setting(
capsys, monkeypatch):
with xo.settings.override(print_mode='print'):
monkeypatch.setenv('XSUITE_PRINT_MODE', 'suppress')
xo._print('visible')
capsys, monkeypatch
):
with xo.settings.override(print_mode="print"):
monkeypatch.setenv("XSUITE_PRINT_MODE", "suppress")
xo._print("visible")

assert capsys.readouterr().out == 'visible\n'
assert capsys.readouterr().out == "visible\n"


@pytest.mark.parametrize('value', ['1', 'true', 'YES', 'on'])
@pytest.mark.parametrize("value", ["1", "true", "YES", "on"])
def test_boolean_environment_true_values(value):
environment = os.environ.copy()
environment['XSUITE_ALLOW_KERNEL_COMPILATION'] = value
environment["XSUITE_ALLOW_KERNEL_COMPILATION"] = value
code = (
'import xobjects as xo; '
'assert xo.settings.allow_kernel_compilation is True; '
'xo.settings.allow_kernel_compilation = False; '
'assert xo.settings.allow_kernel_compilation is False')
"import xobjects as xo; "
"assert xo.settings.allow_kernel_compilation is True; "
"xo.settings.allow_kernel_compilation = False; "
"assert xo.settings.allow_kernel_compilation is False"
)

subprocess.run(
[sys.executable, '-c', code],
[sys.executable, "-c", code],
env=environment,
capture_output=True,
text=True,
check=True,
)


@pytest.mark.parametrize('value', ['0', 'false', 'NO', 'off'])
@pytest.mark.parametrize("value", ["0", "false", "NO", "off"])
def test_boolean_environment_false_values(value):
environment = os.environ.copy()
environment['XSUITE_FORCE_KERNEL_COMPILATION'] = value
environment["XSUITE_FORCE_KERNEL_COMPILATION"] = value
code = (
'import xobjects as xo; '
'assert xo.settings.force_kernel_compilation is False')
"import xobjects as xo; "
"assert xo.settings.force_kernel_compilation is False"
)

subprocess.run(
[sys.executable, '-c', code],
[sys.executable, "-c", code],
env=environment,
capture_output=True,
text=True,
Expand All @@ -161,46 +166,49 @@ def test_boolean_environment_false_values(value):

def test_invalid_boolean_environment_value():
environment = os.environ.copy()
environment['XSUITE_CFFI_FORBID_COMPILE'] = 'sometimes'
environment["XSUITE_CFFI_FORBID_COMPILE"] = "sometimes"

completed = subprocess.run(
[sys.executable, '-c', 'import xobjects'],
[sys.executable, "-c", "import xobjects"],
env=environment,
capture_output=True,
text=True,
)

assert completed.returncode != 0
assert 'Invalid boolean value' in completed.stderr
assert 'xobjects.settings.cffi_forbid_compile' in completed.stderr
assert 'XSUITE_CFFI_FORBID_COMPILE' in completed.stderr
assert "Invalid boolean value" in completed.stderr
assert "xobjects.settings.cffi_forbid_compile" in completed.stderr
assert "XSUITE_CFFI_FORBID_COMPILE" in completed.stderr


def test_runtime_settings_environment_defaults():
environment = os.environ.copy()
environment.update({
'XSUITE_PROGRESS_INDICATOR': 'text',
'XSUITE_FORCE_KERNEL_COMPILATION': 'yes',
'XSUITE_SHOW_KERNEL_DIAGNOSTICS': 'on',
'XSUITE_CFFI_FORBID_COMPILE': 'true',
'XSUITE_CFFI_KEEP_BUILD_FILES': '1',
'XSUITE_CUDA_BACKEND': 'clang',
'XSUITE_CUDA_FAST_COMPILE': 'false',
'XSUITE_CUDA_COMPILER': '/path/to/clang++',
})
environment.update(
{
"XSUITE_PROGRESS_INDICATOR": "text",
"XSUITE_FORCE_KERNEL_COMPILATION": "yes",
"XSUITE_SHOW_KERNEL_DIAGNOSTICS": "on",
"XSUITE_CFFI_FORBID_COMPILE": "true",
"XSUITE_CFFI_KEEP_BUILD_FILES": "1",
"XSUITE_CUDA_BACKEND": "clang",
"XSUITE_CUDA_FAST_COMPILE": "false",
"XSUITE_CUDA_COMPILER": "/path/to/clang++",
}
)
code = (
'import xobjects as xo; '
"import xobjects as xo; "
'assert xo.settings.progress_indicator == "text"; '
'assert xo.settings.force_kernel_compilation is True; '
'assert xo.settings.show_kernel_diagnostics is True; '
'assert xo.settings.cffi_forbid_compile is True; '
'assert xo.settings.cffi_keep_build_files is True; '
"assert xo.settings.force_kernel_compilation is True; "
"assert xo.settings.show_kernel_diagnostics is True; "
"assert xo.settings.cffi_forbid_compile is True; "
"assert xo.settings.cffi_keep_build_files is True; "
'assert xo.settings.cuda_backend == "clang"; '
'assert xo.settings.cuda_fast_compile is False; '
'assert xo.settings.cuda_compiler == "/path/to/clang++"')
"assert xo.settings.cuda_fast_compile is False; "
'assert xo.settings.cuda_compiler == "/path/to/clang++"'
)

subprocess.run(
[sys.executable, '-c', code],
[sys.executable, "-c", code],
env=environment,
capture_output=True,
text=True,
Expand All @@ -209,7 +217,7 @@ def test_runtime_settings_environment_defaults():


@pytest.mark.parametrize(
'allow, force, compilation_allowed',
"allow, force, compilation_allowed",
[
(False, False, False),
(True, False, True),
Expand All @@ -222,21 +230,23 @@ def test_kernel_compilation_settings(allow, force, compilation_allowed):
allow_kernel_compilation=allow,
force_kernel_compilation=force,
):
assert xo.context_cpu.kernel_compilation_allowed(
xo.ContextCpu()) is compilation_allowed
assert (
xo.context_cpu.kernel_compilation_allowed(xo.ContextCpu())
is compilation_allowed
)


def test_user_context_environment_variable(monkeypatch):
monkeypatch.setenv('XOBJECTS_USER_CONTEXT', 'ContextCpu:auto')
monkeypatch.setenv("XOBJECTS_USER_CONTEXT", "ContextCpu:auto")
context = xo.get_user_context()

assert context.openmp_enabled


def test_test_contexts_environment_variable(monkeypatch):
monkeypatch.setenv(
'XOBJECTS_TEST_CONTEXTS',
'ContextCpu;ContextCpu:auto',
"XOBJECTS_TEST_CONTEXTS",
"ContextCpu;ContextCpu:auto",
)

contexts = list(xo.context.get_test_contexts())
Expand All @@ -252,8 +262,8 @@ def test_cffi_forbid_compile_setting():
xo.ContextCpu().build_kernels({})

message = str(err.value)
assert 'xobjects.settings.cffi_forbid_compile' in message
assert 'XSUITE_CFFI_FORBID_COMPILE' in message
assert "xobjects.settings.cffi_forbid_compile" in message
assert "XSUITE_CFFI_FORBID_COMPILE" in message


def test_allow_kernel_compilation_decorator_restores_state():
Expand Down
Loading
Loading