Files
wildminder-ComfyUI-VibeVoice/tests/test_mm_api_surface.py
T
WildAi dc64c17c00 fix: cpu-first loading + neg-branch rope fix
- DF-001..006: loader builds the model entirely on CPU (state dict, load_state_dict, dtype cast, 4-bit); patcher owns the single H2D transfer after ComfyUI load_models_gpu arbitration. Removes the disk->VRAM->RAM->VRAM round-trip; peak load VRAM ~2x -> ~1x model size.

- BUG-011: negative CFG forward passed full-length position_ids with single-token inputs_embeds; transformers 5.x RoPE broadcast expanded q/k (not v) -> KV cache key/value desync -> SDPA crash [12,3] vs [12,2]. Now current-only position_ids.

- Tests: +36 device-flow, +4 neg-position-ids (red/green verified), +scheduler/e2e/mm-surface suites. Full suite 461p/5 pre-existing f/4s.

- Version 2.0.2; untrack .workbuddy-ai, ignore tmp/
2026-08-15 16:46:56 +03:00

87 lines
3.1 KiB
Python

"""D2/D3: ComfyUI API-surface conformance audit.
Asserts that every ``comfy.model_management`` / ``comfy.utils`` symbol the
project relies on actually exists on the real ComfyUI modules in this
checkout. This is a version-drift guard: if ComfyUI renames or removes a
symbol, these tests fail loudly instead of the node crashing at runtime.
"""
import inspect
import comfy.model_management as mm
import comfy.utils as comfy_utils
import folder_paths
class TestModelManagementSurface:
"""Every model_management symbol used by the project must exist."""
USED_SYMBOLS = [
"get_torch_device",
"intermediate_device",
"load_model_gpu",
"unload_all_models",
"soft_empty_cache",
"should_use_bf16",
"should_use_fp16",
"supports_fp8_compute",
"get_autocast_device",
"is_nvidia",
"is_amd",
"mps_mode",
"module_size",
"InterruptProcessingException",
]
def test_all_used_symbols_exist(self):
missing = [s for s in self.USED_SYMBOLS if not hasattr(mm, s)]
assert missing == [], f"comfy.model_management missing symbols: {missing}"
def test_interrupt_is_exception_class(self):
assert inspect.isclass(mm.InterruptProcessingException)
# ComfyUI deliberately subclasses BaseException (not Exception) so a
# bare ``except Exception`` cannot swallow user interrupts. The project's
# catch order (InterruptProcessingException before Exception) relies on
# this — lock it here.
assert issubclass(mm.InterruptProcessingException, BaseException)
assert not issubclass(mm.InterruptProcessingException, Exception)
def test_load_model_gpu_is_callable(self):
assert callable(mm.load_model_gpu)
def test_should_use_bf16_accepts_device_arg(self):
sig = inspect.signature(mm.should_use_bf16)
# Must accept at least one positional (device) argument.
assert len(sig.parameters) >= 1
class TestComfyUtilsSurface:
"""comfy.utils.load_torch_file must exist with a device parameter."""
def test_load_torch_file_exists(self):
assert hasattr(comfy_utils, "load_torch_file")
assert callable(comfy_utils.load_torch_file)
def test_load_torch_file_accepts_device_kwarg(self):
sig = inspect.signature(comfy_utils.load_torch_file)
assert "device" in sig.parameters
def test_progressbar_exists(self):
# generation.py imports ProgressBar from comfy.utils.
assert hasattr(comfy_utils, "ProgressBar")
class TestFolderPathsSurface:
"""folder_paths symbols used by the project must exist."""
def test_folder_paths_symbols_exist(self):
for sym in ("get_folder_paths", "add_model_folder_path",
"supported_pt_extensions", "models_dir",
"folder_names_and_paths"):
assert hasattr(folder_paths, sym), f"folder_paths missing: {sym}"
def test_add_model_folder_path_signature(self):
sig = inspect.signature(folder_paths.add_model_folder_path)
assert "folder_name" in sig.parameters
assert "full_folder_path" in sig.parameters