mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-09-05 07:27:15 +08:00
test(database): validate media identity constraints semantically (#6422)
This commit is contained in:
@@ -71,7 +71,7 @@ ensure_sites_stub()
|
|||||||
|
|
||||||
from alembic.config import Config
|
from alembic.config import Config
|
||||||
from alembic.script import ScriptDirectory
|
from alembic.script import ScriptDirectory
|
||||||
from sqlalchemy import inspect, text
|
from sqlalchemy import inspect, MetaData, Table, text
|
||||||
from sqlalchemy.exc import IntegrityError
|
from sqlalchemy.exc import IntegrityError
|
||||||
|
|
||||||
from app.runtime.config import settings
|
from app.runtime.config import settings
|
||||||
@@ -110,8 +110,8 @@ with get_engine().connect() as connection:
|
|||||||
)
|
)
|
||||||
for index in inspector.get_indexes(table_name)
|
for index in inspector.get_indexes(table_name)
|
||||||
}}
|
}}
|
||||||
constraints = {{
|
constraint_names = {{
|
||||||
constraint["name"]: constraint.get("sqltext") or ""
|
constraint["name"]
|
||||||
for constraint in inspector.get_check_constraints(table_name)
|
for constraint in inspector.get_check_constraints(table_name)
|
||||||
}}
|
}}
|
||||||
assert {{"media_source", "media_id"}}.issubset(columns), (
|
assert {{"media_source", "media_id"}}.issubset(columns), (
|
||||||
@@ -129,57 +129,71 @@ with get_engine().connect() as connection:
|
|||||||
indexes,
|
indexes,
|
||||||
)
|
)
|
||||||
constraint_name = f"ck_{{table_name}}_media_identity"
|
constraint_name = f"ck_{{table_name}}_media_identity"
|
||||||
assert constraint_name in constraints, (
|
assert constraint_name in constraint_names, (
|
||||||
table_name,
|
table_name,
|
||||||
constraints,
|
constraint_names,
|
||||||
)
|
|
||||||
normalized_sql = "".join(
|
|
||||||
constraints[constraint_name].lower().replace('"', '').split()
|
|
||||||
)
|
|
||||||
for text_cast in ("::text[]", "::text", "::charactervarying"):
|
|
||||||
normalized_sql = normalized_sql.replace(text_cast, "")
|
|
||||||
for fragment in (
|
|
||||||
"media_sourceisnull",
|
|
||||||
"media_idisnull",
|
|
||||||
"media_sourceisnotnull",
|
|
||||||
"media_idisnotnull",
|
|
||||||
"length(media_source)",
|
|
||||||
"media_sourcenotlike'%:%'",
|
|
||||||
):
|
|
||||||
assert fragment in normalized_sql, (
|
|
||||||
table_name,
|
|
||||||
constraints[constraint_name],
|
|
||||||
)
|
|
||||||
assert any(
|
|
||||||
trim_form in normalized_sql
|
|
||||||
for trim_form in (
|
|
||||||
"trim(media_id)",
|
|
||||||
"trim(bothfrommedia_id)",
|
|
||||||
)
|
|
||||||
), (table_name, constraints[constraint_name])
|
|
||||||
assert "<>''" in normalized_sql, (
|
|
||||||
table_name,
|
|
||||||
constraints[constraint_name],
|
|
||||||
)
|
|
||||||
assert "<>'0'" in normalized_sql, (
|
|
||||||
table_name,
|
|
||||||
constraints[constraint_name],
|
|
||||||
)
|
)
|
||||||
|
|
||||||
constraint_name = "ck_mediaserveritem_media_identity"
|
required_values = {{
|
||||||
try:
|
"subscribe": {{"name": "constraint-test", "state": "N"}},
|
||||||
with connection.begin_nested():
|
"subscribehistory": {{"name": "constraint-test"}},
|
||||||
connection.execute(
|
"downloadhistory": {{
|
||||||
text(
|
"path": "/constraint-test",
|
||||||
"INSERT INTO mediaserveritem (media_source, media_id) "
|
"type": "电影",
|
||||||
"VALUES (:media_source, :media_id)"
|
"title": "constraint-test",
|
||||||
),
|
}},
|
||||||
{{"media_source": "invalid:source", "media_id": "1"}},
|
"transferhistory": {{"src_storage": "local"}},
|
||||||
)
|
"downloadfailure": {{"fingerprint": "constraint-test"}},
|
||||||
except IntegrityError as error:
|
"mediaserveritem": {{}},
|
||||||
assert constraint_name in str(error.orig), str(error.orig)
|
}}
|
||||||
else:
|
invalid_identities = (
|
||||||
raise AssertionError("格式非法的媒体身份未被具名检查约束拒绝")
|
(None, "1"),
|
||||||
|
("acme.video", None),
|
||||||
|
("", "1"),
|
||||||
|
(" acme.video", "1"),
|
||||||
|
("acme.video ", "1"),
|
||||||
|
("Acme.Video", "1"),
|
||||||
|
("a" * 65, "1"),
|
||||||
|
("invalid:source", "1"),
|
||||||
|
("invalid source", "1"),
|
||||||
|
("acme.video", ""),
|
||||||
|
("acme.video", " "),
|
||||||
|
("acme.video", "0"),
|
||||||
|
)
|
||||||
|
for table_name in media_tables:
|
||||||
|
table = Table(table_name, MetaData(), autoload_with=connection)
|
||||||
|
constraint_name = f"ck_{{table_name}}_media_identity"
|
||||||
|
for media_source, media_id in (
|
||||||
|
(None, None),
|
||||||
|
("acme.video", "custom-1"),
|
||||||
|
):
|
||||||
|
values = {{
|
||||||
|
**required_values[table_name],
|
||||||
|
"media_source": media_source,
|
||||||
|
"media_id": media_id,
|
||||||
|
}}
|
||||||
|
savepoint = connection.begin_nested()
|
||||||
|
try:
|
||||||
|
connection.execute(table.insert(), values)
|
||||||
|
finally:
|
||||||
|
savepoint.rollback()
|
||||||
|
|
||||||
|
for media_source, media_id in invalid_identities:
|
||||||
|
values = {{
|
||||||
|
**required_values[table_name],
|
||||||
|
"media_source": media_source,
|
||||||
|
"media_id": media_id,
|
||||||
|
}}
|
||||||
|
try:
|
||||||
|
with connection.begin_nested():
|
||||||
|
connection.execute(table.insert(), values)
|
||||||
|
except IntegrityError as error:
|
||||||
|
assert constraint_name in str(error.orig), str(error.orig)
|
||||||
|
else:
|
||||||
|
raise AssertionError(
|
||||||
|
"格式非法的媒体身份未被具名检查约束拒绝: "
|
||||||
|
f"{{table_name}}, {{media_source!r}}, {{media_id!r}}"
|
||||||
|
)
|
||||||
""".format(
|
""".format(
|
||||||
media_tables=MEDIA_TABLES,
|
media_tables=MEDIA_TABLES,
|
||||||
legacy_identity_columns=LEGACY_IDENTITY_COLUMNS,
|
legacy_identity_columns=LEGACY_IDENTITY_COLUMNS,
|
||||||
|
|||||||
Reference in New Issue
Block a user