mirror of
https://github.com/LearningCircuit/local-deep-research.git
synced 2026-06-16 03:51:07 +03:00
- Bulk fix import paths from src.local_deep_research to local_deep_research across 190+ test files - Fix test_settings_routes.py: update validate_setting tests to use proper Setting objects instead of incorrect parameter signature - Fix test_research_service.py: remove tests for non-existent functions, correct mimetype assertions for latex export - Fix test_app_factory.py: use truly public IP (8.8.8.8) instead of TEST-NET reserved range for IP validation test - Fix test_api_functions.py: correct patch paths for get_user_db_session, has_request_context, and get_settings_manager - Fix test_news_api.py: correct patch paths for database session Test results: 8592 passing, 175 failing (down from 286), 115 skipped Remaining failures are test isolation issues that pass individually.
184 lines
5.8 KiB
Python
184 lines
5.8 KiB
Python
"""
|
|
Tests for encryption key passing to background threads.
|
|
|
|
Verifies that research threads can access encrypted databases with the correct password.
|
|
"""
|
|
|
|
import threading
|
|
import pytest
|
|
from unittest.mock import patch
|
|
|
|
from tests.test_utils import add_src_to_path
|
|
|
|
add_src_to_path()
|
|
|
|
|
|
class TestThreadContextPasswordStorage:
|
|
"""Test that thread context correctly stores and retrieves passwords."""
|
|
|
|
def test_set_and_get_password_in_same_thread(self):
|
|
"""Password set via set_search_context should be retrievable."""
|
|
from local_deep_research.utilities.thread_context import (
|
|
set_search_context,
|
|
get_search_context,
|
|
)
|
|
|
|
set_search_context(
|
|
{
|
|
"username": "test_user",
|
|
"user_password": "secret123",
|
|
}
|
|
)
|
|
|
|
ctx = get_search_context()
|
|
assert ctx is not None
|
|
assert ctx.get("user_password") == "secret123"
|
|
|
|
def test_context_includes_all_fields(self):
|
|
"""All fields in context should be preserved."""
|
|
from local_deep_research.utilities.thread_context import (
|
|
set_search_context,
|
|
get_search_context,
|
|
)
|
|
|
|
context = {
|
|
"research_id": "res_123",
|
|
"username": "alice",
|
|
"user_password": "pass456",
|
|
"custom_field": "custom_value",
|
|
}
|
|
set_search_context(context)
|
|
|
|
retrieved = get_search_context()
|
|
assert retrieved["research_id"] == "res_123"
|
|
assert retrieved["username"] == "alice"
|
|
assert retrieved["user_password"] == "pass456"
|
|
assert retrieved["custom_field"] == "custom_value"
|
|
|
|
|
|
class TestThreadContextIsolation:
|
|
"""Test that thread context is properly isolated between threads."""
|
|
|
|
def test_child_thread_does_not_inherit_context(self):
|
|
"""A new thread should NOT see the parent thread's context."""
|
|
from local_deep_research.utilities.thread_context import (
|
|
set_search_context,
|
|
get_search_context,
|
|
)
|
|
|
|
child_result = []
|
|
|
|
def child_thread():
|
|
ctx = get_search_context()
|
|
child_result.append(ctx)
|
|
|
|
# Set context in main thread
|
|
set_search_context({"user_password": "main_thread_pass"})
|
|
|
|
# Child thread should not see it
|
|
thread = threading.Thread(target=child_thread)
|
|
thread.start()
|
|
thread.join(timeout=2)
|
|
|
|
assert child_result[0] is None, (
|
|
"Child thread should not inherit parent's context"
|
|
)
|
|
|
|
def test_child_thread_can_set_own_context(self):
|
|
"""A child thread can set and retrieve its own context."""
|
|
from local_deep_research.utilities.thread_context import (
|
|
set_search_context,
|
|
get_search_context,
|
|
)
|
|
|
|
child_result = []
|
|
|
|
def child_thread():
|
|
set_search_context({"user_password": "child_pass"})
|
|
ctx = get_search_context()
|
|
child_result.append(ctx)
|
|
|
|
thread = threading.Thread(target=child_thread)
|
|
thread.start()
|
|
thread.join(timeout=2)
|
|
|
|
assert child_result[0] is not None
|
|
assert child_result[0]["user_password"] == "child_pass"
|
|
|
|
|
|
class TestGetUserDbSessionPasswordRetrieval:
|
|
"""Test that get_user_db_session retrieves password from thread context."""
|
|
|
|
def test_password_retrieved_from_thread_context(self):
|
|
"""get_user_db_session should use password from thread context."""
|
|
from local_deep_research.utilities.thread_context import (
|
|
set_search_context,
|
|
)
|
|
from local_deep_research.database.session_context import (
|
|
get_user_db_session,
|
|
)
|
|
from local_deep_research.database.encrypted_db import db_manager
|
|
from local_deep_research.database import thread_local_session
|
|
|
|
set_search_context(
|
|
{
|
|
"username": "test_user",
|
|
"user_password": "thread_context_password",
|
|
}
|
|
)
|
|
|
|
captured_passwords = []
|
|
|
|
def capture(username, password):
|
|
captured_passwords.append(password)
|
|
raise Exception("Captured")
|
|
|
|
with patch(
|
|
"local_deep_research.database.session_context.has_app_context",
|
|
return_value=False,
|
|
):
|
|
with patch.object(db_manager, "has_encryption", True):
|
|
with patch.object(
|
|
thread_local_session,
|
|
"get_metrics_session",
|
|
side_effect=capture,
|
|
):
|
|
try:
|
|
with get_user_db_session("test_user"):
|
|
pass
|
|
except Exception:
|
|
pass
|
|
|
|
assert len(captured_passwords) == 1
|
|
assert captured_passwords[0] == "thread_context_password"
|
|
|
|
def test_none_password_causes_error_with_encryption(self):
|
|
"""If password is None and encryption is enabled, should raise error."""
|
|
from local_deep_research.utilities.thread_context import (
|
|
set_search_context,
|
|
)
|
|
from local_deep_research.database.session_context import (
|
|
get_user_db_session,
|
|
DatabaseSessionError,
|
|
)
|
|
from local_deep_research.database.encrypted_db import db_manager
|
|
|
|
# Set context with None password
|
|
set_search_context(
|
|
{
|
|
"username": "test_user",
|
|
"user_password": None,
|
|
}
|
|
)
|
|
|
|
with patch(
|
|
"local_deep_research.database.session_context.has_app_context",
|
|
return_value=False,
|
|
):
|
|
with patch.object(db_manager, "has_encryption", True):
|
|
with pytest.raises(DatabaseSessionError) as exc_info:
|
|
with get_user_db_session("test_user"):
|
|
pass
|
|
|
|
assert "requires password" in str(exc_info.value).lower()
|