项目文件夹

文件
wehub-resource-sync eec33d25b2
Build Wheel / build (3.11) (push) Failing after 1s
Build Wheel / build (3.12) (push) Failing after 0s
pre-commit / pre-commit (push) Failing after 1s
chore: import upstream snapshot with attribution
2026-07-13 12:29:08 +08:00

165 行
5.5 KiB
Python

"""
Tests for hook registry.
NOTE: The hook registry is also tested indirectly through a lot of
other tests, e.g., tests/diffusion/distributed/test_sp_plan_hooks.py
"""
from typing import Any
import pytest
from torch import nn
from vllm_omni.diffusion.hooks.base import HookRegistry, ModelHook
DEFAULT_OUT = "ECHO"
OVERRIDE_OUT = "OVERRIDE"
INPUT_KWARG = "inp"
class EchoModule(nn.Module):
"""Just echo the input."""
def __init__(self, *args: Any, **kwargs: Any) -> None:
super().__init__(*args, **kwargs)
def forward(self, *args, **kwargs):
input_val = kwargs[INPUT_KWARG]
return input_val + DEFAULT_OUT
class AppendHook(ModelHook):
"""Append an echo value to the input string on pre / post forward."""
def __init__(self, echo_val: str):
self.echo_val = echo_val
def pre_forward(self, module: nn.Module, *args, **kwargs):
input_val = kwargs[INPUT_KWARG]
return (), {INPUT_KWARG: input_val + self.echo_val}
def post_forward(self, module: nn.Module, output):
return output + self.echo_val
class OverrideAppendHook(AppendHook):
"""Same as AppendHook, but replace the forward call with a different string."""
def new_forward(self, module: nn.Module, *args, **kwargs):
return kwargs[INPUT_KWARG] + OVERRIDE_OUT
def test_register_no_fwd_override_hooks():
"""Ensure registration is correct with no forward hooks."""
mod = EchoModule()
registry = HookRegistry.get_or_create(mod)
first_hook = AppendHook("1")
second_hook = AppendHook("2")
sorted_no_fwd_hooks = [first_hook, second_hook]
# Will add and sort the hook by key
registry.register_hook(name="b", hook=second_hook)
registry.register_hook(name="a", hook=first_hook)
assert len(registry._hooks) == 2
assert len(registry._sorted_hooks) == 2
assert registry._new_fwd_impl_hook is None
# Ensure registering a new hook sorting alphabetically
for actual_hook, expected_hook in zip(registry._sorted_hooks, sorted_no_fwd_hooks):
assert actual_hook is expected_hook
def test_register_with_forward_hooks():
"""Ensure registration is correct with a forward hooks."""
mod = EchoModule()
registry = HookRegistry.get_or_create(mod)
first_hook = AppendHook("1")
second_hook = AppendHook("2")
exec_hook = OverrideAppendHook("3")
sorted_no_fwd_hooks = [first_hook, second_hook]
# Will add and sort the hook by key
registry.register_hook(name="b", hook=second_hook)
registry.register_hook(name="a", hook=first_hook)
registry.register_hook(name="c", hook=exec_hook)
assert len(registry._hooks) == 3
assert len(registry._sorted_hooks) == 3
assert registry._new_fwd_impl_hook is exec_hook
# Ensure registering a new hook sorting alphabetically
for actual_hook, expected_hook in zip(registry._sorted_hooks, sorted_no_fwd_hooks):
assert actual_hook is expected_hook
def test_register_fails_with_multiple_forward_hooks():
"""Ensure registration only allows one hook overriding new_forward"""
mod = EchoModule()
registry = HookRegistry.get_or_create(mod)
registry.register_hook(name="foo", hook=OverrideAppendHook("1"))
with pytest.raises(RuntimeError):
registry.register_hook(name="bar", hook=OverrideAppendHook("2"))
def test_remove_hooks():
"""Ensure removal sorts hooks."""
mod = EchoModule()
registry = HookRegistry.get_or_create(mod)
first_hook = AppendHook("1")
second_hook = AppendHook("2")
exec_hook = OverrideAppendHook("3")
registry.register_hook(name="b", hook=second_hook)
registry.register_hook(name="a", hook=first_hook)
registry.register_hook(name="c", hook=exec_hook)
# Explicitly reorder our hooks to be in the wrong order, since register
# forces them to be sorted too. Ensure that remove the hook will also
# enforce the sorted order.
registry._sorted_hooks = [second_hook, first_hook]
assert registry._new_fwd_impl_hook is exec_hook
registry.remove_hook("c")
assert registry._new_fwd_impl_hook is None
sorted_no_fwd_hooks = [first_hook, second_hook]
for actual_hook, expected_hook in zip(registry._sorted_hooks, sorted_no_fwd_hooks):
assert actual_hook is expected_hook
def test_dispatch_no_fwd_override_hooks():
"""Ensure dispatch runs hooks in deterministic sorted order."""
mod = EchoModule()
registry = HookRegistry.get_or_create(mod)
first_hook = AppendHook("1")
second_hook = AppendHook("2")
# Register will sort the hooks, so hook 1 will run first
# on preprocess and last in post process
registry.register_hook(name="2", hook=second_hook)
registry.register_hook(name="1", hook=first_hook)
res = registry.dispatch(inp="")
assert isinstance(res, str)
assert res == f"12{DEFAULT_OUT}21"
def test_dispatch_with_fwd_hooks():
"""Ensure dispatch runs hooks in deterministic sorted order."""
mod = EchoModule()
registry = HookRegistry.get_or_create(mod)
first_hook = AppendHook("1")
second_hook = AppendHook("2")
exec_hook = OverrideAppendHook("3")
# Register will sort the hooks, so hook 1 will run first on preprocess and last in
# post process. Since the override hook mutates forward, it will run last even
# though the name of the exec_hook is alphabetically before the second hook.
registry.register_hook(name="c", hook=second_hook)
registry.register_hook(name="a", hook=first_hook)
registry.register_hook(name="b", hook=exec_hook)
res = registry.dispatch(inp="")
assert isinstance(res, str)
assert res == f"123{OVERRIDE_OUT}321"