2026-01-05 21:18:11 +08:00
|
|
|
# SPDX-License-Identifier: Apache-2.0
|
2026-09-01 22:53:53 +08:00
|
|
|
# SPDX-FileCopyrightText: Copyright contributors to the vLLM-Omni project
|
2026-01-05 21:18:11 +08:00
|
|
|
|
|
|
|
|
"""
|
2026-01-28 22:12:52 +08:00
|
|
|
Unit tests for DiffusionWorker class.
|
2026-01-05 21:18:11 +08:00
|
|
|
|
2026-01-28 22:12:52 +08:00
|
|
|
This module tests the DiffusionWorker implementation:
|
2026-01-05 21:18:11 +08:00
|
|
|
- sleep: Putting worker into sleep mode (levels 1 and 2)
|
|
|
|
|
- wake_up: Waking worker from sleep mode
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
import pytest
|
|
|
|
|
import torch
|
2026-02-26 17:08:39 +08:00
|
|
|
from pytest_mock import MockerFixture
|
2026-01-05 21:18:11 +08:00
|
|
|
|
2026-08-18 15:00:24 +08:00
|
|
|
from vllm_omni.diffusion.worker.diffusion_worker import DiffusionWorker
|
2026-01-05 21:18:11 +08:00
|
|
|
|
2026-04-21 07:19:53 +07:00
|
|
|
pytestmark = [pytest.mark.core_model, pytest.mark.diffusion, pytest.mark.gpu]
|
2026-02-09 16:49:45 +08:00
|
|
|
|
2026-01-05 21:18:11 +08:00
|
|
|
|
2026-06-20 08:31:39 +08:00
|
|
|
def patch_cumem_allocator(mocker: MockerFixture):
|
|
|
|
|
mock_allocator_class = mocker.Mock()
|
|
|
|
|
mocker.patch(
|
|
|
|
|
"vllm_omni.diffusion.worker.diffusion_worker._get_cumem_allocator_class",
|
|
|
|
|
return_value=mock_allocator_class,
|
|
|
|
|
)
|
|
|
|
|
return mock_allocator_class
|
|
|
|
|
|
|
|
|
|
|
2026-01-05 21:18:11 +08:00
|
|
|
@pytest.fixture
|
2026-02-26 17:08:39 +08:00
|
|
|
def mock_od_config(mocker: MockerFixture):
|
2026-01-05 21:18:11 +08:00
|
|
|
"""Create a mock OmniDiffusionConfig."""
|
2026-02-26 17:08:39 +08:00
|
|
|
config = mocker.Mock()
|
2026-01-05 21:18:11 +08:00
|
|
|
config.num_gpus = 1
|
|
|
|
|
config.master_port = 12345
|
|
|
|
|
config.enable_sleep_mode = False
|
|
|
|
|
config.cache_backend = None
|
|
|
|
|
config.cache_config = None
|
|
|
|
|
config.model = "test-model"
|
|
|
|
|
return config
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture
|
2026-02-26 17:08:39 +08:00
|
|
|
def mock_gpu_worker(mocker: MockerFixture, mock_od_config):
|
2026-01-28 22:12:52 +08:00
|
|
|
"""Create a DiffusionWorker with mocked initialization."""
|
2026-02-26 17:08:39 +08:00
|
|
|
mocker.patch.object(DiffusionWorker, "init_device")
|
|
|
|
|
mocker.patch.object(DiffusionWorker, "load_model")
|
|
|
|
|
worker = DiffusionWorker(local_rank=0, rank=0, od_config=mock_od_config)
|
|
|
|
|
# Mock the model_runner with pipeline
|
|
|
|
|
worker.model_runner = mocker.Mock()
|
|
|
|
|
worker.model_runner.pipeline = mocker.Mock()
|
|
|
|
|
worker.device = torch.device("cuda", 0)
|
|
|
|
|
worker._sleep_saved_buffers = {}
|
|
|
|
|
return worker
|
2026-01-05 21:18:11 +08:00
|
|
|
|
|
|
|
|
|
2026-01-28 22:12:52 +08:00
|
|
|
class TestDiffusionWorkerSleep:
|
|
|
|
|
"""Test DiffusionWorker.sleep method."""
|
2026-01-05 21:18:11 +08:00
|
|
|
|
2026-04-21 07:19:53 +07:00
|
|
|
@pytest.fixture(autouse=True)
|
|
|
|
|
def setup_allocator(self, mocker: MockerFixture):
|
|
|
|
|
"""
|
|
|
|
|
Unified interception of Allocators, and provision of default security values.
|
|
|
|
|
"""
|
2026-06-20 08:31:39 +08:00
|
|
|
self.mock_allocator_class = patch_cumem_allocator(mocker)
|
2026-04-21 07:19:53 +07:00
|
|
|
self.mock_allocator = mocker.Mock()
|
|
|
|
|
self.mock_allocator_class.get_instance.return_value = self.mock_allocator
|
|
|
|
|
self.mock_allocator.get_current_usage.return_value = 4 * 1024**3
|
|
|
|
|
self.mock_allocator.sleep = mocker.Mock()
|
|
|
|
|
|
2026-02-26 17:08:39 +08:00
|
|
|
def test_sleep_level_1(self, mocker: MockerFixture, mock_gpu_worker):
|
2026-01-05 21:18:11 +08:00
|
|
|
"""Test sleep mode level 1 (offload weights only)."""
|
2026-06-20 08:31:39 +08:00
|
|
|
mock_allocator_class = patch_cumem_allocator(mocker)
|
2026-04-21 07:19:53 +07:00
|
|
|
mock_platform = mocker.patch("vllm_omni.diffusion.worker.diffusion_worker.current_omni_platform")
|
|
|
|
|
mock_platform.get_free_memory.side_effect = [10 * 1024**3, 12 * 1024**3]
|
|
|
|
|
mock_platform.get_device_total_memory.return_value = 80 * 1024**3
|
2026-02-26 17:08:39 +08:00
|
|
|
mock_get_process_memory = mocker.patch("vllm_omni.diffusion.worker.diffusion_worker.get_process_gpu_memory")
|
|
|
|
|
|
2026-02-12 12:17:54 +00:00
|
|
|
# Setup process-scoped memory mocks
|
|
|
|
|
# Before sleep: 3GB used
|
|
|
|
|
# After sleep: 1GB used (freed 2GB)
|
2026-04-21 07:19:53 +07:00
|
|
|
initial_usage = 3 * 1024**3
|
2026-02-12 12:17:54 +00:00
|
|
|
mock_get_process_memory.side_effect = [
|
2026-04-21 07:19:53 +07:00
|
|
|
initial_usage,
|
2026-02-12 12:17:54 +00:00
|
|
|
1 * 1024**3,
|
2026-01-05 21:18:11 +08:00
|
|
|
]
|
|
|
|
|
|
|
|
|
|
# Setup allocator mock
|
2026-02-26 17:08:39 +08:00
|
|
|
mock_allocator = mocker.Mock()
|
|
|
|
|
mock_allocator_class.get_instance = mocker.Mock(return_value=mock_allocator)
|
|
|
|
|
mock_allocator.sleep = mocker.Mock()
|
2026-04-21 07:19:53 +07:00
|
|
|
mock_allocator.get_current_usage.return_value = initial_usage
|
2026-01-05 21:18:11 +08:00
|
|
|
|
|
|
|
|
# Call sleep with level 1
|
|
|
|
|
result = mock_gpu_worker.sleep(level=1)
|
|
|
|
|
|
|
|
|
|
# Verify sleep was called with correct tags
|
|
|
|
|
mock_allocator.sleep.assert_called_once_with(offload_tags=("weights",))
|
2026-04-21 07:19:53 +07:00
|
|
|
assert bool(result) is True
|
2026-01-05 21:18:11 +08:00
|
|
|
# Verify buffers were NOT saved (level 1 doesn't save buffers)
|
|
|
|
|
assert len(mock_gpu_worker._sleep_saved_buffers) == 0
|
|
|
|
|
|
2026-02-26 17:08:39 +08:00
|
|
|
def test_sleep_level_2(self, mocker: MockerFixture, mock_gpu_worker):
|
2026-01-05 21:18:11 +08:00
|
|
|
"""Test sleep mode level 2 (offload all, save buffers)."""
|
2026-06-20 08:31:39 +08:00
|
|
|
mock_allocator_class = patch_cumem_allocator(mocker)
|
2026-04-21 07:19:53 +07:00
|
|
|
mock_platform = mocker.patch("vllm_omni.diffusion.worker.diffusion_worker.current_omni_platform")
|
|
|
|
|
mock_platform.get_free_memory.side_effect = [5 * 1024**3, 10 * 1024**3]
|
|
|
|
|
mock_platform.get_device_total_memory.return_value = 80 * 1024**3
|
2026-02-26 17:08:39 +08:00
|
|
|
mock_get_process_memory = mocker.patch("vllm_omni.diffusion.worker.diffusion_worker.get_process_gpu_memory")
|
|
|
|
|
|
2026-02-12 12:17:54 +00:00
|
|
|
# Setup process-scoped memory mocks
|
2026-04-21 07:19:53 +07:00
|
|
|
initial_usage = 5 * 1024**3
|
2026-02-12 12:17:54 +00:00
|
|
|
mock_get_process_memory.side_effect = [
|
2026-04-21 07:19:53 +07:00
|
|
|
initial_usage, # Before sleep
|
2026-02-12 12:17:54 +00:00
|
|
|
1 * 1024**3, # After sleep (freed 4GB)
|
2026-01-05 21:18:11 +08:00
|
|
|
]
|
|
|
|
|
|
|
|
|
|
# Setup allocator mock
|
2026-02-26 17:08:39 +08:00
|
|
|
mock_allocator = mocker.Mock()
|
|
|
|
|
mock_allocator_class.get_instance = mocker.Mock(return_value=mock_allocator)
|
|
|
|
|
mock_allocator.sleep = mocker.Mock()
|
2026-04-21 07:19:53 +07:00
|
|
|
mock_allocator.get_current_usage.return_value = initial_usage
|
2026-01-05 21:18:11 +08:00
|
|
|
|
|
|
|
|
# Mock pipeline buffers
|
|
|
|
|
mock_buffer1 = torch.randn(10, 10)
|
|
|
|
|
mock_buffer2 = torch.randn(20, 20)
|
2026-02-26 17:08:39 +08:00
|
|
|
mock_gpu_worker.model_runner.pipeline.named_buffers = mocker.Mock(
|
2026-01-05 21:18:11 +08:00
|
|
|
return_value=[
|
|
|
|
|
("buffer1", mock_buffer1),
|
|
|
|
|
("buffer2", mock_buffer2),
|
|
|
|
|
]
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# Call sleep with level 2
|
|
|
|
|
result = mock_gpu_worker.sleep(level=2)
|
|
|
|
|
|
|
|
|
|
# Verify sleep was called with empty tags (offload all)
|
|
|
|
|
mock_allocator.sleep.assert_called_once_with(offload_tags=tuple())
|
2026-04-21 07:19:53 +07:00
|
|
|
assert bool(result) is True
|
2026-01-05 21:18:11 +08:00
|
|
|
|
|
|
|
|
# Verify buffers were saved
|
|
|
|
|
assert len(mock_gpu_worker._sleep_saved_buffers) == 2
|
|
|
|
|
assert "buffer1" in mock_gpu_worker._sleep_saved_buffers
|
|
|
|
|
assert "buffer2" in mock_gpu_worker._sleep_saved_buffers
|
|
|
|
|
|
2026-09-01 22:53:53 +08:00
|
|
|
def test_sleep_level_2_releases_captures_through_the_model_runner(self, mocker: MockerFixture, mock_gpu_worker):
|
|
|
|
|
"""Level 2 discards the memory captures were recorded against, and the
|
|
|
|
|
runner owns the release. The worker asks it once and does not reach past
|
|
|
|
|
it into the pipeline."""
|
|
|
|
|
mock_platform = mocker.patch("vllm_omni.diffusion.worker.diffusion_worker.current_omni_platform")
|
|
|
|
|
mock_platform.get_free_memory.side_effect = [10 * 1024**3, 12 * 1024**3]
|
|
|
|
|
mock_platform.get_device_total_memory.return_value = 80 * 1024**3
|
|
|
|
|
mocker.patch("vllm_omni.diffusion.worker.diffusion_worker.get_process_gpu_memory", side_effect=[0, 0])
|
|
|
|
|
mock_gpu_worker.model_runner.pipeline.named_buffers = mocker.Mock(return_value=[])
|
|
|
|
|
|
|
|
|
|
mock_gpu_worker.sleep(level=2)
|
|
|
|
|
|
|
|
|
|
mock_gpu_worker.model_runner.release_captured_graphs.assert_called_once_with()
|
|
|
|
|
mock_gpu_worker.model_runner.pipeline.release_captured_graphs.assert_not_called()
|
|
|
|
|
|
2026-02-26 17:08:39 +08:00
|
|
|
def test_sleep_memory_freed_validation(self, mocker: MockerFixture, mock_gpu_worker):
|
2026-01-05 21:18:11 +08:00
|
|
|
"""Test that sleep validates memory was actually freed."""
|
2026-06-20 08:31:39 +08:00
|
|
|
mock_allocator_class = patch_cumem_allocator(mocker)
|
2026-04-21 07:19:53 +07:00
|
|
|
mock_platform = mocker.patch("vllm_omni.diffusion.worker.diffusion_worker.current_omni_platform")
|
|
|
|
|
mock_platform.get_free_memory.return_value = 10 * 1024**3
|
|
|
|
|
mock_platform.get_device_total_memory.return_value = 80 * 1024**3
|
2026-02-26 17:08:39 +08:00
|
|
|
mock_get_process_memory = mocker.patch("vllm_omni.diffusion.worker.diffusion_worker.get_process_gpu_memory")
|
|
|
|
|
|
2026-02-12 12:17:54 +00:00
|
|
|
# Simulate process memory increase (should trigger assertion error)
|
2026-04-21 07:19:53 +07:00
|
|
|
initial_usage = 1 * 1024**3
|
2026-02-12 12:17:54 +00:00
|
|
|
mock_get_process_memory.side_effect = [
|
2026-04-21 07:19:53 +07:00
|
|
|
initial_usage, # Before sleep: 1GB used
|
2026-02-12 12:17:54 +00:00
|
|
|
3 * 1024**3, # After sleep: 3GB used (negative freed)
|
2026-01-05 21:18:11 +08:00
|
|
|
]
|
|
|
|
|
|
2026-02-26 17:08:39 +08:00
|
|
|
mock_allocator = mocker.Mock()
|
|
|
|
|
mock_allocator_class.get_instance = mocker.Mock(return_value=mock_allocator)
|
|
|
|
|
mock_allocator.sleep = mocker.Mock()
|
2026-04-21 07:19:53 +07:00
|
|
|
mock_allocator.get_current_usage.return_value = initial_usage
|
2026-01-05 21:18:11 +08:00
|
|
|
|
|
|
|
|
# This should raise an assertion error
|
2026-04-21 07:19:53 +07:00
|
|
|
result = mock_gpu_worker.sleep(level=1)
|
|
|
|
|
assert result == initial_usage
|
2026-01-05 21:18:11 +08:00
|
|
|
|
2026-02-26 17:08:39 +08:00
|
|
|
def test_sleep_falls_back_to_device_memory_when_nvml_unavailable(self, mocker: MockerFixture, mock_gpu_worker):
|
2026-02-12 12:17:54 +00:00
|
|
|
"""Test sleep uses device-scoped fallback when NVML is unavailable."""
|
2026-02-26 17:08:39 +08:00
|
|
|
|
2026-06-20 08:31:39 +08:00
|
|
|
mock_allocator_class = patch_cumem_allocator(mocker)
|
2026-02-26 17:08:39 +08:00
|
|
|
mock_platform = mocker.patch("vllm_omni.diffusion.worker.diffusion_worker.current_omni_platform")
|
|
|
|
|
mock_get_process_memory = mocker.patch("vllm_omni.diffusion.worker.diffusion_worker.get_process_gpu_memory")
|
2026-02-12 12:17:54 +00:00
|
|
|
mock_get_process_memory.side_effect = [None, None]
|
|
|
|
|
mock_platform.get_free_memory.side_effect = [
|
|
|
|
|
1 * 1024**3, # Before sleep
|
|
|
|
|
3 * 1024**3, # After sleep
|
|
|
|
|
]
|
|
|
|
|
mock_platform.get_device_total_memory.return_value = 8 * 1024**3
|
|
|
|
|
|
2026-02-26 17:08:39 +08:00
|
|
|
mock_allocator = mocker.Mock()
|
|
|
|
|
mock_allocator_class.get_instance = mocker.Mock(return_value=mock_allocator)
|
|
|
|
|
mock_allocator.sleep = mocker.Mock()
|
2026-04-21 07:19:53 +07:00
|
|
|
mock_allocator.get_current_usage.return_value = 2 * 1024**3
|
2026-02-12 12:17:54 +00:00
|
|
|
|
|
|
|
|
result = mock_gpu_worker.sleep(level=1)
|
|
|
|
|
|
|
|
|
|
mock_allocator.sleep.assert_called_once_with(offload_tags=("weights",))
|
2026-04-21 07:19:53 +07:00
|
|
|
assert bool(result) is True
|
2026-02-12 12:17:54 +00:00
|
|
|
|
2026-01-05 21:18:11 +08:00
|
|
|
|
2026-01-28 22:12:52 +08:00
|
|
|
class TestDiffusionWorkerWakeUp:
|
|
|
|
|
"""Test DiffusionWorker.wake_up method."""
|
2026-01-05 21:18:11 +08:00
|
|
|
|
2026-02-26 17:08:39 +08:00
|
|
|
def test_wake_up_without_buffers(self, mocker: MockerFixture, mock_gpu_worker):
|
2026-01-05 21:18:11 +08:00
|
|
|
"""Test wake_up without saved buffers (level 1 sleep)."""
|
2026-06-20 08:31:39 +08:00
|
|
|
mock_allocator_class = patch_cumem_allocator(mocker)
|
2026-02-26 17:08:39 +08:00
|
|
|
|
2026-01-05 21:18:11 +08:00
|
|
|
# Setup allocator mock
|
2026-02-26 17:08:39 +08:00
|
|
|
mock_allocator = mocker.Mock()
|
|
|
|
|
mock_allocator_class.get_instance = mocker.Mock(return_value=mock_allocator)
|
|
|
|
|
mock_allocator.wake_up = mocker.Mock()
|
2026-04-21 07:19:53 +07:00
|
|
|
mock_allocator.get_current_usage.return_value = 10 * 1024**3
|
2026-01-05 21:18:11 +08:00
|
|
|
|
|
|
|
|
# Ensure no saved buffers
|
|
|
|
|
mock_gpu_worker._sleep_saved_buffers = {}
|
|
|
|
|
|
|
|
|
|
# Call wake_up
|
|
|
|
|
result = mock_gpu_worker.wake_up(tags=["weights"])
|
|
|
|
|
|
|
|
|
|
# Verify allocator.wake_up was called
|
|
|
|
|
mock_allocator.wake_up.assert_called_once_with(["weights"])
|
2026-04-21 07:19:53 +07:00
|
|
|
assert bool(result) is True
|
2026-01-05 21:18:11 +08:00
|
|
|
|
2026-02-26 17:08:39 +08:00
|
|
|
def test_wake_up_with_buffers(self, mocker: MockerFixture, mock_gpu_worker):
|
2026-01-05 21:18:11 +08:00
|
|
|
"""Test wake_up with saved buffers (level 2 sleep)."""
|
2026-06-20 08:31:39 +08:00
|
|
|
mock_allocator_class = patch_cumem_allocator(mocker)
|
2026-02-26 17:08:39 +08:00
|
|
|
|
2026-01-05 21:18:11 +08:00
|
|
|
# Setup allocator mock
|
2026-02-26 17:08:39 +08:00
|
|
|
mock_allocator = mocker.Mock()
|
|
|
|
|
mock_allocator_class.get_instance = mocker.Mock(return_value=mock_allocator)
|
|
|
|
|
mock_allocator.wake_up = mocker.Mock()
|
2026-04-21 07:19:53 +07:00
|
|
|
mock_allocator.get_current_usage.return_value = 10 * 1024**3
|
2026-01-05 21:18:11 +08:00
|
|
|
|
|
|
|
|
# Create saved buffers
|
|
|
|
|
saved_buffer1 = torch.randn(10, 10)
|
|
|
|
|
saved_buffer2 = torch.randn(20, 20)
|
|
|
|
|
mock_gpu_worker._sleep_saved_buffers = {
|
|
|
|
|
"buffer1": saved_buffer1,
|
|
|
|
|
"buffer2": saved_buffer2,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Mock pipeline buffers (these will be restored)
|
2026-02-26 17:08:39 +08:00
|
|
|
mock_buffer1 = mocker.Mock()
|
|
|
|
|
mock_buffer1.data = mocker.Mock()
|
|
|
|
|
mock_buffer2 = mocker.Mock()
|
|
|
|
|
mock_buffer2.data = mocker.Mock()
|
2026-01-05 21:18:11 +08:00
|
|
|
|
2026-02-26 17:08:39 +08:00
|
|
|
mock_gpu_worker.model_runner.pipeline.named_buffers = mocker.Mock(
|
2026-01-05 21:18:11 +08:00
|
|
|
return_value=[
|
|
|
|
|
("buffer1", mock_buffer1),
|
|
|
|
|
("buffer2", mock_buffer2),
|
|
|
|
|
]
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# Call wake_up
|
|
|
|
|
result = mock_gpu_worker.wake_up(tags=None)
|
|
|
|
|
|
|
|
|
|
# Verify allocator.wake_up was called
|
|
|
|
|
mock_allocator.wake_up.assert_called_once_with(None)
|
|
|
|
|
|
|
|
|
|
# Verify buffers were restored
|
|
|
|
|
mock_buffer1.data.copy_.assert_called_once()
|
|
|
|
|
mock_buffer2.data.copy_.assert_called_once()
|
|
|
|
|
|
|
|
|
|
# Verify saved buffers were cleared
|
|
|
|
|
assert len(mock_gpu_worker._sleep_saved_buffers) == 0
|
2026-04-21 07:19:53 +07:00
|
|
|
assert bool(result) is True
|
2026-01-05 21:18:11 +08:00
|
|
|
|
2026-02-26 17:08:39 +08:00
|
|
|
def test_wake_up_partial_buffer_restore(self, mocker: MockerFixture, mock_gpu_worker):
|
2026-01-05 21:18:11 +08:00
|
|
|
"""Test wake_up only restores buffers that were saved."""
|
2026-06-20 08:31:39 +08:00
|
|
|
mock_allocator_class = patch_cumem_allocator(mocker)
|
2026-02-26 17:08:39 +08:00
|
|
|
|
2026-01-05 21:18:11 +08:00
|
|
|
# Setup allocator mock
|
2026-02-26 17:08:39 +08:00
|
|
|
mock_allocator = mocker.Mock()
|
|
|
|
|
mock_allocator_class.get_instance = mocker.Mock(return_value=mock_allocator)
|
|
|
|
|
mock_allocator.wake_up = mocker.Mock()
|
2026-04-21 07:19:53 +07:00
|
|
|
mock_allocator.get_current_usage.return_value = 10 * 1024**3
|
2026-01-05 21:18:11 +08:00
|
|
|
|
|
|
|
|
# Only save buffer1, not buffer2
|
|
|
|
|
saved_buffer1 = torch.randn(10, 10)
|
|
|
|
|
mock_gpu_worker._sleep_saved_buffers = {
|
|
|
|
|
"buffer1": saved_buffer1,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Mock pipeline has both buffers
|
2026-02-26 17:08:39 +08:00
|
|
|
mock_buffer1 = mocker.Mock()
|
|
|
|
|
mock_buffer1.data = mocker.Mock()
|
|
|
|
|
mock_buffer2 = mocker.Mock()
|
|
|
|
|
mock_buffer2.data = mocker.Mock()
|
2026-01-05 21:18:11 +08:00
|
|
|
|
2026-02-26 17:08:39 +08:00
|
|
|
mock_gpu_worker.model_runner.pipeline.named_buffers = mocker.Mock(
|
2026-01-05 21:18:11 +08:00
|
|
|
return_value=[
|
|
|
|
|
("buffer1", mock_buffer1),
|
|
|
|
|
("buffer2", mock_buffer2),
|
|
|
|
|
]
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# Call wake_up
|
|
|
|
|
result = mock_gpu_worker.wake_up()
|
|
|
|
|
|
|
|
|
|
# Verify only buffer1 was restored
|
|
|
|
|
mock_buffer1.data.copy_.assert_called_once()
|
|
|
|
|
# buffer2 should NOT be restored since it wasn't saved
|
|
|
|
|
mock_buffer2.data.copy_.assert_not_called()
|
|
|
|
|
|
2026-05-13 22:22:43 +08:00
|
|
|
assert result is True
|
2026-09-06 01:29:59 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
class TestDiffusionWorkerInitLoraManager:
|
|
|
|
|
"""Test DiffusionWorker.init_lora_manager method."""
|
|
|
|
|
|
|
|
|
|
def test_skips_when_lora_already_fused(self, mocker: MockerFixture, mock_gpu_worker):
|
|
|
|
|
"""When pipeline.lora_is_fused is True, init_lora_manager returns immediately."""
|
|
|
|
|
from vllm_omni.diffusion.lora.manager import LoRABackend
|
|
|
|
|
|
|
|
|
|
mock_gpu_worker.od_config.lora_backend = LoRABackend.DISTILL
|
|
|
|
|
mock_gpu_worker.od_config.lora_path = "/path/to/lora.safetensors"
|
|
|
|
|
mock_gpu_worker.od_config.lora_scale = 1.0
|
|
|
|
|
|
|
|
|
|
pipeline = mock_gpu_worker.model_runner.pipeline
|
|
|
|
|
pipeline.lora_is_fused = True
|
|
|
|
|
pipeline.load_lora_weights = mocker.Mock()
|
|
|
|
|
|
|
|
|
|
mock_gpu_worker.init_lora_manager()
|
|
|
|
|
|
|
|
|
|
pipeline.load_lora_weights.assert_not_called()
|
|
|
|
|
assert mock_gpu_worker.lora_manager is None
|
|
|
|
|
|
|
|
|
|
def test_distill_backend_fuses_and_marks_flag_when_not_pre_fused(self, mocker: MockerFixture, mock_gpu_worker):
|
|
|
|
|
"""When lora_is_fused is False, distill backend calls load_lora_weights and sets flag."""
|
|
|
|
|
from vllm_omni.diffusion.lora.manager import LoRABackend
|
|
|
|
|
|
|
|
|
|
mock_gpu_worker.od_config.lora_backend = LoRABackend.DISTILL
|
|
|
|
|
mock_gpu_worker.od_config.lora_path = "/path/to/lora.safetensors"
|
|
|
|
|
mock_gpu_worker.od_config.lora_scale = 1.0
|
|
|
|
|
|
|
|
|
|
pipeline = mock_gpu_worker.model_runner.pipeline
|
|
|
|
|
pipeline.lora_is_fused = False
|
|
|
|
|
pipeline.load_lora_weights = mocker.Mock()
|
|
|
|
|
|
|
|
|
|
mock_gpu_worker.init_lora_manager()
|
|
|
|
|
|
|
|
|
|
pipeline.load_lora_weights.assert_called_once_with("/path/to/lora.safetensors")
|
|
|
|
|
assert pipeline.lora_is_fused is True
|