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

207 lines
6.8 KiB
Python

#!/usr/bin/env python3
"""
Test backwards compatibility for encrypted databases.
This test ensures that databases created with previous versions can still
be opened with the current version. This prevents breaking changes like
salt modifications from going undetected.
The key tests are:
1. TestSaltStability - Fast tests that verify encryption constants haven't changed
2. TestBackwardsCompatibility - Slow test that actually installs previous PyPI version
The salt stability tests run in CI and catch 99% of breaking changes.
The full backwards compatibility test can be run manually with:
pytest tests/performance/database/test_backwards_compatibility.py -m slow --run-slow
"""
import os
import subprocess
import sys
import tempfile
from pathlib import Path
import pytest
# Path to the script that creates a database using the installed package
# This is in a separate file for better IDE support (syntax highlighting, linting)
CREATE_DB_SCRIPT_PATH = (
Path(__file__).parent / "scripts" / "create_compat_db.py"
)
class TestBackwardsCompatibility:
"""Test that current version can open databases from previous versions."""
@pytest.fixture
def temp_dir(self):
"""Create a temporary directory for test databases."""
with tempfile.TemporaryDirectory() as tmpdir:
yield Path(tmpdir)
def get_previous_version(self) -> str:
"""Get the previous version number from PyPI."""
result = subprocess.run(
[
sys.executable,
"-m",
"pip",
"index",
"versions",
"local-deep-research",
],
capture_output=True,
text=True,
)
if result.returncode != 0:
# Fallback: try to get from pip show
result = subprocess.run(
[sys.executable, "-m", "pip", "show", "local-deep-research"],
capture_output=True,
text=True,
)
# Can't determine previous version
pytest.skip("Could not determine previous version from PyPI")
# Parse versions from output
# Output format: "local-deep-research (1.3.21)\nAvailable versions: 1.3.21, 1.3.20, ..."
for line in result.stdout.split("\n"):
if "Available versions:" in line:
versions = line.split(":")[1].strip().split(", ")
if len(versions) >= 2:
return versions[1] # Second version is the previous one
pytest.skip("Could not find previous version")
@pytest.mark.slow
@pytest.mark.timeout(600) # 10 minutes - installing PyPI package takes time
@pytest.mark.skipif(
os.environ.get("RUN_SLOW_TESTS") != "true",
reason="Slow test - set RUN_SLOW_TESTS=true to run",
)
def test_open_database_from_previous_version(self, temp_dir, monkeypatch):
"""
Test that we can open a database created with the previous PyPI version.
This test:
1. Installs the previous version in an isolated venv
2. Creates a database using that version
3. Verifies the current version can open it and read data
"""
# Get previous version
try:
previous_version = self.get_previous_version()
except Exception as e:
pytest.skip(f"Could not get previous version: {e}")
# Create isolated venv for previous version
venv_dir = temp_dir / "prev_venv"
db_dir = temp_dir / "databases"
db_dir.mkdir()
# Create venv
result = subprocess.run(
[sys.executable, "-m", "venv", str(venv_dir)],
capture_output=True,
text=True,
)
if result.returncode != 0:
pytest.skip(f"Could not create venv: {result.stderr}")
# Get venv python
if sys.platform == "win32":
venv_python = venv_dir / "Scripts" / "python.exe"
else:
venv_python = venv_dir / "bin" / "python"
# Install previous version (with timeout)
# Package has many dependencies, needs sufficient time
result = subprocess.run(
[
str(venv_python),
"-m",
"pip",
"install",
f"local-deep-research=={previous_version}",
"--quiet",
],
capture_output=True,
text=True,
timeout=600, # 10 minute timeout - package has many dependencies
)
if result.returncode != 0:
pytest.skip(f"Could not install previous version: {result.stderr}")
# Create database with previous version
username = "compat_test_user"
password = "CompatTestPass123!"
# Copy the script to temp dir (script is in separate file for IDE support)
script_file = temp_dir / "create_db.py"
script_file.write_text(CREATE_DB_SCRIPT_PATH.read_text())
result = subprocess.run(
[
str(venv_python),
str(script_file),
str(db_dir),
username,
password,
],
capture_output=True,
text=True,
timeout=60,
)
if result.returncode != 0:
pytest.fail(
f"Could not create database with previous version: {result.stderr}"
)
# Now test opening with current version
monkeypatch.setattr(
"local_deep_research.database.encrypted_db.get_data_directory",
lambda: db_dir,
)
from local_deep_research.database.encrypted_db import (
DatabaseManager,
)
from local_deep_research.database.models import UserSettings
manager = DatabaseManager()
manager.data_dir = db_dir / "encrypted_databases"
# Try to open the database
engine = manager.open_user_database(username, password)
assert engine is not None, (
f"Failed to open database created with version {previous_version}. "
"This likely means a breaking change was introduced (e.g., salt change)."
)
# Verify we can read the data
session = manager.get_session(username)
setting = (
session.query(UserSettings)
.filter_by(key="test.backwards_compat")
.first()
)
assert setting is not None, (
"Could not read data from previous version database"
)
assert setting.value["version"] == "previous"
assert setting.value["test"] is True
session.close()
manager.close_user_database(username)
# Note: Salt stability tests have been moved to test_encryption_constants.py
# This file now only contains the slow PyPI backwards compatibility test.
if __name__ == "__main__":
pytest.main([__file__, "-v"])