chore: import upstream snapshot with attribution
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

This commit is contained in:
wehub-resource-sync
2026-07-13 13:08:55 +08:00
commit 7a0da7932b
2985 changed files with 1049377 additions and 0 deletions
@@ -0,0 +1,264 @@
# allow: no-sut-import — exercises sqlcipher_compat via importlib reload to cover ImportError paths (dynamic import)
"""
Comprehensive tests for local_deep_research.database.sqlcipher_compat module.
Tests the compatibility layer logic, feature detection, and ImportError
behavior when sqlcipher3 is unavailable.
"""
import importlib
import sys
import types
from unittest import mock
import pytest
# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------
MODULE_PATH = "local_deep_research.database.sqlcipher_compat"
def _fresh_import():
"""Re-import sqlcipher_compat so module-level code re-executes."""
mod = importlib.import_module(MODULE_PATH)
importlib.reload(mod)
return mod
# ---------------------------------------------------------------------------
# 1. Successful import path sqlcipher3 is available
# ---------------------------------------------------------------------------
class TestGetSqlcipherModuleSuccess:
"""When sqlcipher3 can be imported, get_sqlcipher_module should return it."""
def test_returns_sqlcipher3_module(self):
"""get_sqlcipher_module returns the sqlcipher3 module object."""
fake_sqlcipher3 = types.ModuleType("sqlcipher3")
fake_sqlcipher3.dbapi2 = object()
with mock.patch.dict(sys.modules, {"sqlcipher3": fake_sqlcipher3}):
mod = _fresh_import()
result = mod.get_sqlcipher_module()
assert result is fake_sqlcipher3
def test_returned_module_has_dbapi2(self):
"""The returned module should carry a dbapi2 attribute."""
fake_sqlcipher3 = types.ModuleType("sqlcipher3")
sentinel = object()
fake_sqlcipher3.dbapi2 = sentinel
with mock.patch.dict(sys.modules, {"sqlcipher3": fake_sqlcipher3}):
mod = _fresh_import()
result = mod.get_sqlcipher_module()
assert hasattr(result, "dbapi2")
assert result.dbapi2 is sentinel
def test_multiple_calls_return_same_module(self):
"""Repeated calls should consistently return the same module."""
fake_sqlcipher3 = types.ModuleType("sqlcipher3")
fake_sqlcipher3.dbapi2 = object()
with mock.patch.dict(sys.modules, {"sqlcipher3": fake_sqlcipher3}):
mod = _fresh_import()
r1 = mod.get_sqlcipher_module()
r2 = mod.get_sqlcipher_module()
assert r1 is r2
def test_returns_module_with_connect_attribute(self):
"""Validates that a module with a connect() callable works fine."""
fake_sqlcipher3 = types.ModuleType("sqlcipher3")
fake_sqlcipher3.dbapi2 = types.ModuleType("sqlcipher3.dbapi2")
fake_sqlcipher3.connect = lambda db: None
with mock.patch.dict(sys.modules, {"sqlcipher3": fake_sqlcipher3}):
mod = _fresh_import()
result = mod.get_sqlcipher_module()
assert callable(result.connect)
# ---------------------------------------------------------------------------
# 2. ImportError path sqlcipher3 is NOT available
# ---------------------------------------------------------------------------
class TestGetSqlcipherModuleImportError:
"""When sqlcipher3 cannot be imported, get_sqlcipher_module must raise."""
def _block_sqlcipher3(self):
"""Return a context manager that makes `import sqlcipher3` fail."""
original_import = (
__builtins__.__import__
if hasattr(__builtins__, "__import__")
else __import__
)
def _guarded_import(name, *args, **kwargs):
if name == "sqlcipher3":
raise ImportError("No module named 'sqlcipher3'")
return original_import(name, *args, **kwargs)
return mock.patch("builtins.__import__", side_effect=_guarded_import)
def test_raises_import_error(self):
"""An ImportError must be raised when sqlcipher3 is absent."""
with self._block_sqlcipher3():
# Remove sqlcipher3 from sys.modules if cached
with mock.patch.dict(sys.modules, {"sqlcipher3": None}):
mod = _fresh_import()
with pytest.raises(ImportError):
mod.get_sqlcipher_module()
def test_error_message_mentions_sqlcipher3(self):
"""The error message should mention sqlcipher3."""
with self._block_sqlcipher3():
with mock.patch.dict(sys.modules, {"sqlcipher3": None}):
mod = _fresh_import()
with pytest.raises(ImportError, match="sqlcipher3"):
mod.get_sqlcipher_module()
def test_error_message_mentions_pdm_install(self):
"""The error message should mention pdm install."""
with self._block_sqlcipher3():
with mock.patch.dict(sys.modules, {"sqlcipher3": None}):
mod = _fresh_import()
with pytest.raises(ImportError, match="pdm install"):
mod.get_sqlcipher_module()
def test_error_message_mentions_system_library(self):
"""The error message should mention SQLCipher system library."""
with self._block_sqlcipher3():
with mock.patch.dict(sys.modules, {"sqlcipher3": None}):
mod = _fresh_import()
with pytest.raises(
ImportError, match="SQLCipher system library"
):
mod.get_sqlcipher_module()
# ---------------------------------------------------------------------------
# 3. Feature detection module attributes
# ---------------------------------------------------------------------------
class TestModuleAttributes:
"""Verify the public API surface of the compat module."""
def test_get_sqlcipher_module_is_callable(self):
"""get_sqlcipher_module must be a callable."""
mod = importlib.import_module(MODULE_PATH)
assert callable(mod.get_sqlcipher_module)
def test_module_has_docstring(self):
"""The module should have a docstring describing its purpose."""
mod = importlib.import_module(MODULE_PATH)
assert mod.__doc__ is not None
assert "SQLCipher" in mod.__doc__
def test_function_has_docstring(self):
"""get_sqlcipher_module should have a docstring."""
mod = importlib.import_module(MODULE_PATH)
assert mod.get_sqlcipher_module.__doc__ is not None
def test_docstring_documents_return_type(self):
"""The function docstring should mention Returns."""
mod = importlib.import_module(MODULE_PATH)
assert "Returns" in mod.get_sqlcipher_module.__doc__
def test_docstring_documents_raises(self):
"""The function docstring should mention Raises / ImportError."""
mod = importlib.import_module(MODULE_PATH)
assert "ImportError" in mod.get_sqlcipher_module.__doc__
# ---------------------------------------------------------------------------
# 4. Platform compat the module works regardless of which package provides
# the sqlcipher3 namespace (sqlcipher3-binary vs sqlcipher3 source build).
# ---------------------------------------------------------------------------
class TestPlatformCompatibility:
"""Simulates different package backends behind the sqlcipher3 name."""
def test_binary_package(self):
"""Simulate sqlcipher3-binary providing the sqlcipher3 namespace."""
fake = types.ModuleType("sqlcipher3")
fake._binary = True # marker attribute
fake.dbapi2 = types.ModuleType("sqlcipher3.dbapi2")
with mock.patch.dict(sys.modules, {"sqlcipher3": fake}):
mod = _fresh_import()
result = mod.get_sqlcipher_module()
assert result._binary is True
def test_source_package(self):
"""Simulate sqlcipher3 built from source."""
fake = types.ModuleType("sqlcipher3")
fake._source = True
fake.dbapi2 = types.ModuleType("sqlcipher3.dbapi2")
with mock.patch.dict(sys.modules, {"sqlcipher3": fake}):
mod = _fresh_import()
result = mod.get_sqlcipher_module()
assert result._source is True
def test_module_identity_preserved(self):
"""The compat layer should not wrap or proxy the module."""
fake = types.ModuleType("sqlcipher3")
fake.dbapi2 = object()
with mock.patch.dict(sys.modules, {"sqlcipher3": fake}):
mod = _fresh_import()
result = mod.get_sqlcipher_module()
# Must be the exact same object, not a wrapper
assert result is fake
assert type(result) is types.ModuleType
# ---------------------------------------------------------------------------
# 5. Edge cases
# ---------------------------------------------------------------------------
class TestEdgeCases:
"""Assorted edge-case scenarios."""
def test_import_error_is_not_generic_exception(self):
"""The raised exception must be ImportError, not a generic Exception."""
with mock.patch.dict(sys.modules, {"sqlcipher3": None}):
mod = _fresh_import()
with pytest.raises(ImportError) as exc_info:
mod.get_sqlcipher_module()
assert type(exc_info.value) is ImportError
def test_no_side_effects_on_sys_modules(self):
"""Calling get_sqlcipher_module should not add unexpected entries."""
fake = types.ModuleType("sqlcipher3")
fake.dbapi2 = object()
before_keys = set(sys.modules.keys())
with mock.patch.dict(sys.modules, {"sqlcipher3": fake}):
mod = _fresh_import()
mod.get_sqlcipher_module()
after_keys = set(sys.modules.keys())
# Only the compat module itself (from reload) may appear; no others
unexpected = after_keys - before_keys - {MODULE_PATH}
# Filter out __pycache__ or bytecode artifacts
unexpected = {k for k in unexpected if "sqlcipher" in k.lower()}
assert not unexpected, f"Unexpected modules added: {unexpected}"
def test_reloadable(self):
"""The module should be safely reloadable."""
fake = types.ModuleType("sqlcipher3")
fake.dbapi2 = object()
with mock.patch.dict(sys.modules, {"sqlcipher3": fake}):
mod = _fresh_import()
# Reload again
importlib.reload(mod)
result = mod.get_sqlcipher_module()
assert result is fake