test_mysql_integration.py 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. from __future__ import annotations
  2. import os
  3. from pathlib import Path
  4. from urllib.parse import urlparse
  5. import pytest
  6. from alembic import command
  7. from alembic.config import Config
  8. from sqlalchemy import create_engine, text
  9. # alembic配置按测试文件位置解析,不依赖 pytest 启动目录。
  10. ALEMBIC_INI = Path(__file__).resolve().parents[2] / "migrations" / "alembic.ini"
  11. @pytest.mark.integration
  12. def test_mysql_q3_upgrade_downgrade_upgrade_when_test_database_is_configured(
  13. monkeypatch,
  14. ):
  15. database_url = os.environ.get("DMS_TEST_DATABASE_URL", "").strip()
  16. if not database_url:
  17. pytest.skip("未配置DMS_TEST_DATABASE_URL,未执行真实MySQL迁移")
  18. if not database_url.startswith("mysql+pymysql://"):
  19. pytest.fail("DMS_TEST_DATABASE_URL必须使用mysql+pymysql")
  20. database_name = urlparse(database_url).path.lstrip("/")
  21. if not database_name.endswith("_test"):
  22. pytest.fail("为避免误操作,MySQL测试库名称必须以_test结尾")
  23. monkeypatch.setenv("DMS_DATABASE_URL", database_url)
  24. config = Config(str(ALEMBIC_INI))
  25. command.upgrade(config, "head")
  26. # 仅清理独立测试库中的B8测试审计;迁移自身不修改历史审计。
  27. # 0015降级守卫要求IP条目/机构分配/IP审计全部清空
  28. # (test_ip_entries等文件残留的审计记录会触发该守卫)。
  29. engine = create_engine(database_url)
  30. with engine.begin() as connection:
  31. connection.execute(
  32. text(
  33. "DELETE FROM sys_audit_log "
  34. "WHERE action_type = 'RESTORE_DOCUMENT' "
  35. "OR action_type IN "
  36. "('CREATE_IP_ENTRY', 'EDIT_IP_ENTRY', 'DELETE_IP_ENTRY', "
  37. "'ASSIGN_ORG_IP')"
  38. )
  39. )
  40. connection.execute(text("DELETE FROM sys_org_ip_assignment"))
  41. connection.execute(text("DELETE FROM sys_ip_entry"))
  42. # 0003明确阻止正文结果的有损降级;测试库先回到可安全降级状态。
  43. # 0019同样阻止已有提取失败记录的降级,一并清空。
  44. connection.execute(
  45. text(
  46. "UPDATE doc_document SET content_text = NULL, "
  47. "content_extract_status = 'UNSUPPORTED', "
  48. "content_extract_error = NULL, "
  49. "content_extracted_at = NULL, "
  50. "search_text = CONCAT_WS(' ', document_name, summary)"
  51. )
  52. )
  53. engine.dispose()
  54. command.downgrade(config, "0002_add_restore_audit_action")
  55. command.upgrade(config, "head")