Files
WildAi 8404100f31 perf: stream sharded/quant loads, console progress, dep cleanup
- streaming per-tensor assign (tensor.clone) replaces merged-dict
  load_state_dict_sharded — mmap views were keeping all shard files
  resident after partial offload (+15GB ghost RSS, Pin-error flood);
  private RAM copies pin reliably and release shard mappings early
- console progress bar during TTS/ASR generation (progress_utils)
- GGUF read-only mmap no longer warns (copy before from_numpy)
- demote internal load-narration logs to DEBUG (success-only INFO)
- drop dead deps (einops, tokenizers, s3tokenizer, conformer),
  add accelerate to pyproject (4-bit path needs it), requirements
  trimmed to non-ComfyUI-bundled packages; parity guard tests
2026-09-01 21:39:58 +03:00

152 lines
5.4 KiB
Python

"""Tests for modules/progress_utils.py.
``ProgressBarWithConsole`` must drive both ComfyUI progress surfaces:
* the **frontend** bar (``comfy.utils.ProgressBar``), and
* the **standard tqdm console bar** that every sampler prints to the terminal.
The frontend bar is exercised with the *real* ``comfy.utils.ProgressBar``
(its server hook is ``None`` under test, so ``update_absolute`` only tracks
``current``/``total``). The console bar is asserted through a patched
``tqdm`` so no real terminal output is produced. The global
``comfy.utils.PROGRESS_BAR_ENABLED`` flag — the same one ``nodes.py`` reads to
build the samplers' ``disable_pbar`` — must gate the console bar.
"""
import pytest
from unittest.mock import patch
import comfy.utils
from ComfyUI_VibeVoice.modules import progress_utils
from ComfyUI_VibeVoice.modules.progress_utils import ProgressBarWithConsole
@pytest.fixture
def mock_tqdm():
"""Patch the tqdm class referenced inside progress_utils.
No real console bar is created; assertions go through
``mock_tqdm.return_value`` (the would-be bar instance).
"""
with patch.object(progress_utils, "tqdm") as m:
yield m
class TestFrontendBar:
"""The wrapper must forward every update to the real frontend bar."""
def test_ui_bar_tracks_absolute_update(self, mock_tqdm):
bar = ProgressBarWithConsole(10)
bar.update_absolute(7)
assert bar._ui.current == 7
assert bar._ui.total == 10
def test_ui_bar_total_reset_via_update_absolute(self, mock_tqdm):
bar = ProgressBarWithConsole(10)
bar.update_absolute(3, total=100)
assert bar._ui.total == 100
assert bar._ui.current == 3
def test_ui_bar_clamps_value_to_total(self, mock_tqdm):
bar = ProgressBarWithConsole(10)
bar.update_absolute(999)
assert bar._ui.current == 10
def test_update_relative_accumulates(self, mock_tqdm):
bar = ProgressBarWithConsole(10)
bar.update(3)
bar.update(4)
assert bar._ui.current == 7
def test_total_and_current_properties_delegate(self, mock_tqdm):
bar = ProgressBarWithConsole(10)
bar.update_absolute(6, total=42)
assert bar.total == 42
assert bar.current == 6
def test_node_id_forwarded_to_ui_bar(self, mock_tqdm):
with patch.object(comfy.utils, "ProgressBar") as mock_ui_cls:
ProgressBarWithConsole(10, node_id="node_7")
mock_ui_cls.assert_called_once_with(10, node_id="node_7")
class TestConsoleBar:
"""The wrapper must mirror updates to a lazily-created tqdm console bar."""
def test_console_bar_created_lazily_on_first_update(self, mock_tqdm):
bar = ProgressBarWithConsole(10)
mock_tqdm.assert_not_called()
bar.update_absolute(1)
mock_tqdm.assert_called_once_with(total=10)
def test_console_bar_tracks_position(self, mock_tqdm):
bar = ProgressBarWithConsole(10)
bar.update_absolute(4)
console = mock_tqdm.return_value
assert console.n == 4
console.refresh.assert_called()
def test_console_bar_uses_corrected_total_on_first_update(self, mock_tqdm):
# Streaming path: constructed with a total=1 placeholder, corrected on
# the first callback. Lazy creation must see the corrected total.
bar = ProgressBarWithConsole(1)
bar.update_absolute(1, total=512)
mock_tqdm.assert_called_once_with(total=512)
assert mock_tqdm.return_value.n == 1
def test_console_bar_resyncs_total_after_creation(self, mock_tqdm):
bar = ProgressBarWithConsole(10)
bar.update_absolute(1)
bar.update_absolute(2, total=50)
console = mock_tqdm.return_value
assert console.total == 50
assert console.n == 2
def test_console_bar_n_clamped_via_ui(self, mock_tqdm):
bar = ProgressBarWithConsole(10)
bar.update_absolute(999)
assert mock_tqdm.return_value.n == 10
def test_no_console_bar_when_disabled(self, mock_tqdm):
with patch.object(comfy.utils, "PROGRESS_BAR_ENABLED", False):
bar = ProgressBarWithConsole(10)
bar.update_absolute(5)
mock_tqdm.assert_not_called()
def test_frontend_bar_still_updates_when_console_disabled(self, mock_tqdm):
with patch.object(comfy.utils, "PROGRESS_BAR_ENABLED", False):
bar = ProgressBarWithConsole(10)
bar.update_absolute(5)
assert bar._ui.current == 5
class TestClose:
"""close() finalizes the console bar and must be safe to call anytime."""
def test_close_closes_console_bar(self, mock_tqdm):
bar = ProgressBarWithConsole(10)
bar.update_absolute(1)
console = mock_tqdm.return_value
bar.close()
console.close.assert_called_once()
def test_close_safe_when_no_bar_created(self, mock_tqdm):
bar = ProgressBarWithConsole(10)
bar.close()
mock_tqdm.return_value.close.assert_not_called()
def test_close_idempotent(self, mock_tqdm):
bar = ProgressBarWithConsole(10)
bar.update_absolute(1)
console = mock_tqdm.return_value
bar.close()
bar.close()
console.close.assert_called_once()
def test_close_safe_when_disabled(self, mock_tqdm):
with patch.object(comfy.utils, "PROGRESS_BAR_ENABLED", False):
bar = ProgressBarWithConsole(10)
bar.update_absolute(5)
bar.close()
mock_tqdm.assert_not_called()