Spaces:
Running on Zero
Running on Zero
Download tests/test_render_modes.py from cpuai/blender-render-studio: direct link, hf CLI and curl.
- Browser
- Download file 4.91 kB
-
https://huggingface.co/spaces/cpuai/blender-render-studio/resolve/main/tests/test_render_modes.py
- Command line
-
hf download hf://spaces/cpuai/blender-render-studio/tests/test_render_modes.py
-
curl -L -o test_render_modes.py https://huggingface.co/spaces/cpuai/blender-render-studio/resolve/main/tests/test_render_modes.py
4.91 kB
| import importlib | |
| import os | |
| import sys | |
| from pathlib import Path | |
| import pytest | |
| sys.path.insert(0, str(Path(__file__).resolve().parents[1])) | |
| from render_config import RenderConfig, parse_config | |
| from blender_runtime import _worker_environment | |
| def test_explicit_cpu_bypasses_zerogpu_even_when_deployment_is_zerogpu(monkeypatch): | |
| import service | |
| monkeypatch.setenv('RENDER_BACKEND', 'zerogpu') | |
| cfg = parse_config('{"device":"CPU"}') | |
| assert (cfg.engine, cfg.device) == ('EEVEE', 'CPU') | |
| assert service._backend(cfg) == 'cpu' | |
| calls = [] | |
| monkeypatch.setattr(service, 'run_task', lambda *args: calls.append('cpu') or {'ok': True}) | |
| monkeypatch.setattr(service, '_zero_render', lambda *args: pytest.fail('CPU must not allocate a GPU')) | |
| service._execute({}, Path('/tmp'), service._backend(cfg), cfg, Path('/tmp/mode-test.log')) | |
| assert calls == ['cpu'] | |
| def test_default_gpu_and_cycles_only_devices_are_validated(monkeypatch): | |
| import service | |
| from spaces.config import Config | |
| monkeypatch.setenv('RENDER_BACKEND', 'auto') | |
| monkeypatch.setattr(Config, 'zero_gpu', True) | |
| assert (RenderConfig().engine, RenderConfig().device) == ('EEVEE', 'AUTO') | |
| assert service._backend(RenderConfig()) == 'zerogpu' | |
| assert service._backend(RenderConfig(engine='CYCLES', device='AUTO')) == 'zerogpu' | |
| assert service._backend(RenderConfig(engine='CYCLES', device='CPU')) == 'cpu' | |
| with pytest.raises(ValueError, match='CUDA / OPTIX'): | |
| RenderConfig(engine='EEVEE', device='CUDA') | |
| def test_software_gl_environment_does_not_leak_into_gpu_jobs(monkeypatch): | |
| monkeypatch.setenv('LIBGL_ALWAYS_SOFTWARE', 'true') | |
| monkeypatch.setenv('GALLIUM_DRIVER', 'llvmpipe') | |
| cpu = _worker_environment({'engine': 'EEVEE', 'device': 'CPU'}) | |
| gpu = _worker_environment({'engine': 'EEVEE', 'device': 'AUTO'}) | |
| assert cpu['LIBGL_ALWAYS_SOFTWARE'] == 'true' | |
| assert cpu['GALLIUM_DRIVER'] == 'llvmpipe' | |
| assert 'LIBGL_ALWAYS_SOFTWARE' not in gpu | |
| assert 'GALLIUM_DRIVER' not in gpu | |
| def test_lock_released_while_forked_worker_still_holds_descriptor(tmp_path): | |
| import service | |
| r, w = os.pipe() | |
| child = None | |
| try: | |
| with service._lock(tmp_path): | |
| child = os.fork() | |
| if child == 0: | |
| os.close(w) | |
| os.read(r, 1) | |
| os._exit(0) | |
| # Child still owns an inherited descriptor, but must not own the lock. | |
| with service._lock(tmp_path): | |
| pass | |
| finally: | |
| if child: | |
| os.write(w, b'x') | |
| os.waitpid(child, 0) | |
| os.close(r) | |
| os.close(w) | |
| def test_legacy_jobs_resume_with_cycles(): | |
| import service | |
| assert service._config({'config': {'device': 'AUTO'}}).engine == 'CYCLES' | |
| assert service._config({'config': {'engine': 'EEVEE', 'device': 'CPU'}}).engine == 'EEVEE' | |
| def test_zerogpu_preserves_worker_error_details(monkeypatch): | |
| import service | |
| def failed_worker(*args): | |
| raise RuntimeError('EGL initialization failed: no graphics device') | |
| monkeypatch.setattr(service, 'run_task', failed_worker) | |
| report = service._allocated_render({}, '/tmp/probe.log', '', 30) | |
| assert not report['ok'] | |
| assert 'no graphics device' in report['error'] | |
| def test_eevee_gpu_probe_is_explicit_and_truthful(monkeypatch): | |
| import service | |
| configs = [] | |
| def probe(cfg): | |
| configs.append(cfg) | |
| return {'ok': False, 'gpu_verified': False, 'error': 'No EGL device'}, [], None | |
| monkeypatch.setattr(service, '_self_test', probe) | |
| report, _, _ = service.eevee_gpu_self_test() | |
| assert configs[0].engine == 'EEVEE' and configs[0].device == 'AUTO' | |
| assert not report['gpu_eevee_usable'] | |
| assert 'No EGL device' == report['error'] | |
| def test_requested_zerogpu_size_routes_exactly_once(monkeypatch): | |
| import service | |
| calls = [] | |
| monkeypatch.setattr(service, '_zero_render', lambda *a: calls.append('large') or {'ok': True}) | |
| monkeypatch.setattr(service, '_zero_render_xlarge', lambda *a: calls.append('xlarge') or {'ok': True}) | |
| for size in ('large', 'xlarge'): | |
| cfg = RenderConfig(gpu_size=size) | |
| service._execute({}, Path('/tmp'), 'zerogpu', cfg, Path('/tmp/probe.log')) | |
| assert calls == ['large', 'xlarge'] | |
| def test_graphics_probe_preserves_requested_backend_and_size(monkeypatch): | |
| import service | |
| configs = [] | |
| monkeypatch.setattr(service, '_self_test', lambda cfg: (configs.append(cfg) or | |
| {'ok': True, 'gpu_verified': True}, [], None)) | |
| report, _, _ = service.eevee_gpu_self_test('xlarge', 'vulkan') | |
| assert configs[0].gpu_size == 'xlarge' and configs[0].graphics_backend == 'vulkan' | |
| assert report['gpu_eevee_usable'] | |
| with pytest.raises(ValueError): | |
| RenderConfig(graphics_backend='opengl --python unsafe.py') | |