test_db_upgrade.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. """db_upgrade 纯逻辑测试(不连接任何数据库)。"""
  2. from alembic.config import Config
  3. from alembic.script import ScriptDirectory
  4. from dms.db_upgrade import _mask_password, resolve_migrations_dir, run_upgrade
  5. def _script() -> ScriptDirectory:
  6. cfg = Config()
  7. cfg.set_main_option("script_location", str(resolve_migrations_dir()))
  8. return ScriptDirectory.from_config(cfg)
  9. def test_resolve_migrations_dir_contains_env_and_versions():
  10. migrations = resolve_migrations_dir()
  11. assert (migrations / "env.py").exists()
  12. assert (migrations / "versions").is_dir()
  13. def test_migration_chain_head_and_steps_from_0013():
  14. """远端生产库 0013 → head 恰好经过 0014~0035。"""
  15. script = _script()
  16. assert script.get_current_head() == "0035_drop_audit_action_check"
  17. steps = [
  18. r.revision
  19. for r in reversed(
  20. list(script.walk_revisions("0013_document_password_lock", "head"))
  21. )
  22. ]
  23. assert steps == [
  24. "0013_document_password_lock",
  25. "0014_document_relations",
  26. "0015_login_ip_restriction",
  27. "0016_portal_user_provision",
  28. "0017_category_type_display_name",
  29. "0018_sub_plan_binding",
  30. "0019_content_extract_error",
  31. "0020_sub_plan_to_attachment",
  32. "0021_remove_assigned_scope",
  33. "0022_login_lockout",
  34. "0023_admin_permissions",
  35. "0024_manage_permission_matrix",
  36. "0025_move_audit_actions",
  37. "0026_borrow_permission",
  38. "0027_ui_theme",
  39. "0028_backup_audit_actions",
  40. "0029_system_management",
  41. "0030_role_edit_permission",
  42. "0031_user_sort_no",
  43. "0032_user_managed_org",
  44. "0033_role_upload_permission",
  45. "0034_role_anchor_self",
  46. "0035_drop_audit_action_check",
  47. ]
  48. def test_run_upgrade_lists_pending_steps_excluding_current(monkeypatch, capsys):
  49. """0016 升级到 head:待执行清单含 0017~0035,当前版本不重复出现。"""
  50. monkeypatch.setenv("DMS_DATABASE_URL", "mysql+pymysql://u:secret@127.0.0.1:3306/dms")
  51. versions = iter(["0016_portal_user_provision", "0035_drop_audit_action_check"])
  52. monkeypatch.setattr(
  53. "dms.db_upgrade._read_current_version", lambda url: next(versions)
  54. )
  55. monkeypatch.setattr("alembic.command.upgrade", lambda cfg, rev: None)
  56. assert run_upgrade(assume_yes=True) == 0
  57. out = capsys.readouterr().out
  58. assert " - 0017_category_type_display_name" in out
  59. assert " - 0018_sub_plan_binding" in out
  60. assert " - 0019_content_extract_error" in out
  61. assert " - 0020_sub_plan_to_attachment" in out
  62. assert " - 0021_remove_assigned_scope" in out
  63. assert " - 0022_login_lockout" in out
  64. assert " - 0023_admin_permissions" in out
  65. assert " - 0024_manage_permission_matrix" in out
  66. assert " - 0025_move_audit_actions" in out
  67. assert " - 0026_borrow_permission" in out
  68. assert " - 0027_ui_theme" in out
  69. assert " - 0028_backup_audit_actions" in out
  70. assert " - 0029_system_management" in out
  71. assert " - 0030_role_edit_permission" in out
  72. assert " - 0031_user_sort_no" in out
  73. assert " - 0032_user_managed_org" in out
  74. assert " - 0033_role_upload_permission" in out
  75. assert " - 0034_role_anchor_self" in out
  76. assert " - 0035_drop_audit_action_check" in out
  77. assert " - 0016" not in out
  78. assert "secret" not in out # 输出中的地址必须已脱敏
  79. def test_mask_password():
  80. url = "mysql+pymysql://dms_app:secret-pwd@203.0.113.10:3306/dms?charset=utf8mb4"
  81. assert (
  82. _mask_password(url)
  83. == "mysql+pymysql://dms_app:***@203.0.113.10:3306/dms?charset=utf8mb4"
  84. )
  85. assert _mask_password("sqlite:///foo.db") == "sqlite:///foo.db"
  86. def test_run_upgrade_requires_database_url(monkeypatch, capsys):
  87. """未配置 DMS_DATABASE_URL 时拒绝执行(fail-fast,绝不 fallback 到 ini 地址)。"""
  88. monkeypatch.delenv("DMS_DATABASE_URL", raising=False)
  89. assert run_upgrade(assume_yes=True) == 2
  90. assert "DMS_DATABASE_URL" in capsys.readouterr().out