Files
wehub-resource-sync 7a0da7932b
OSV-Scanner (Scheduled) / scan-scheduled (push) Failing after 0s
Create Release / test-gate (push) Has been cancelled
Create Release / release-gate (push) Has been cancelled
Create Release / ci-gate (push) Has been cancelled
Create Release / version-check (push) Has been cancelled
Create Release / e2e-test-gate (push) Has been cancelled
Create Release / responsive-test-gate (push) Has been cancelled
Create Release / compat-test-gate (push) Has been cancelled
Create Release / compose-integration-gate (push) Has been cancelled
Create Release / vulture-gate (push) Has been cancelled
Create Release / build (push) Has been cancelled
Create Release / provenance (push) Has been cancelled
Create Release / prerelease-docker (push) Has been cancelled
Create Release / publish-docker (push) Has been cancelled
Create Release / create-release (push) Has been cancelled
Create Release / cleanup-changelog (push) Has been cancelled
Create Release / trigger-pypi (push) Has been cancelled
Create Release / monitor-pypi (push) Has been cancelled
Create Release / Clean up orphan prerelease tags and signatures (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-form] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-metrics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-workflow] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-core] (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [history-news] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [library] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [link-analytics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-core] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-lifecycle] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [error-benchmark] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) (push) Has been cancelled
Docker Tests (Consolidated) / Accessibility Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Unit Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Example Tests (push) Has been cancelled
Docker Tests (Consolidated) / Production Image Smoke Test (push) Has been cancelled
Docker Tests (Consolidated) / Infrastructure Tests (push) Has been cancelled
OSSF Scorecard / OSSF Security Scorecard Analysis (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [mobile] (push) Has been cancelled
Backwards Compatibility / Verify Encryption Constants (push) Has been cancelled
Backwards Compatibility / PyPI Version Compatibility (push) Has been cancelled
Backwards Compatibility / Database Migration Tests (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Docker Tests (Consolidated) / detect-changes (push) Has been cancelled
Docker Tests (Consolidated) / Build Test Image (push) Has been cancelled
Docker Tests (Consolidated) / All Pytest Tests + Coverage (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [accessibility] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [api-crud] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-login] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-register] (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:08:55 +08:00

86 lines
2.9 KiB
Python

"""Tests for the daemon-thread excepthook.
Covers:
- _install_thread_excepthook logs uncaught exceptions from daemon threads.
- _perform_post_login_tasks wraps its body so an otherwise-uncaught exception
from inside the `with` context managers is logged instead of disappearing.
"""
import threading
from unittest.mock import MagicMock, patch
def test_install_thread_excepthook_logs_uncaught_exception():
"""After installing the hook, an uncaught exception on a daemon thread
must be logged at ERROR level including the exception type and the
thread name. Without this, silent crashes in the queue processor
or APScheduler jobs are the mechanism by which the login path
gradually starves.
"""
from local_deep_research.web.app import _install_thread_excepthook
previous = threading.excepthook
_install_thread_excepthook()
try:
with patch("local_deep_research.web.app.logger") as mock_logger:
def raiser():
raise RuntimeError("boom from daemon")
t = threading.Thread(target=raiser, name="test-daemon", daemon=True)
t.start()
t.join(timeout=2.0)
assert not t.is_alive()
assert mock_logger.error.called, "excepthook did not log"
logged = mock_logger.error.call_args[0][0]
assert "test-daemon" in logged
assert "RuntimeError" in logged
assert "boom from daemon" in logged
finally:
threading.excepthook = previous
def test_perform_post_login_tasks_catches_outer_exceptions():
"""If the outer structure of _perform_post_login_tasks itself raises
(for example from inside a `with` context manager's __enter__) —
not inside a per-step try/except — the wrapper must log the
exception and not let the daemon thread die silently.
"""
from local_deep_research.web.auth import routes
with (
patch.object(
routes,
"_perform_post_login_tasks_body",
side_effect=RuntimeError("outer failure"),
),
patch.object(routes, "logger") as mock_logger,
):
# Must not raise.
routes._perform_post_login_tasks("alice", "pw")
assert mock_logger.exception.called
msg = mock_logger.exception.call_args[0][0]
assert "alice" in msg
assert "crashed" in msg.lower() or "post-login" in msg.lower()
def test_perform_post_login_tasks_body_runs_when_no_outer_error():
"""Positive path: when the body succeeds, the wrapper forwards to
it exactly once with the right args, and does not log any
crash.
"""
from local_deep_research.web.auth import routes
body = MagicMock()
with (
patch.object(routes, "_perform_post_login_tasks_body", body),
patch.object(routes, "logger") as mock_logger,
):
routes._perform_post_login_tasks("bob", "pw")
body.assert_called_once_with("bob", "pw")
mock_logger.exception.assert_not_called()